如何压缩?

解读

面试官抛出“如何压缩?”这一看似简短的问题,往往并不是只想听你背命令,而是想验证你对 CouchDB 存储机制、运维成本、国内云环境限制、离线同步场景 的综合理解。国内自建机房磁盘贵、云盘按量计费,加上移动应用离线数据膨胀,“压缩”=“降本+提效+保同步”,必须给出可落地的完整方案。

知识点

  1. 文件级压缩:CouchDB 3.x 默认启用 Snappy 压缩 存储 .couch 文件,旧版本需手动开启 compression=snappy
  2. 视图压缩:视图索引 .view 文件同样走 Snappy,但 只有视图第一次写入后才生效,重建视图会重新压缩。
  3. 附件压缩content_typetext/*application/jsonapplication/javascript可压缩类型 才会被压缩;二进制如 image/png 直接跳过。
  4. 复制压缩多主复制 走 HTTP 时,请求头 Accept-Encoding:gzip 由 Erlang 客户端自动携带,节省跨机房流量 60% 以上,国内云厂商跨区流量 0.8 元/GB,压缩直接等于省钱。
  5. 运维级压缩couch_compactor 进程自动做 在线合并+压缩,但国内云主机 IO 打满会被限流,需调优 compaction_daemonmin_file_sizecheck_interval避开业务高峰
  6. 离线场景:PouchDB 同步到 CouchDB 时,本地 WAL 量 随离线时间线性增长,需在移动端做 local doc 过滤+同步筛选,否则压缩收益被初始同步流量吃掉。

答案

“CouchDB 的压缩是分层的,我通常按三步走:
第一步,存储层:确认 local.ini[couchdb] file_compression = snappy,对 3.x 已默认开启;若集群版本低于 2.2,先滚动升级节点,再逐节点执行 curl -X POST http://node:5984/_compact/{db} 触发文件级压缩,可节省 30%~50% 磁盘。
第二步,视图层:设计文档里把易变字段移出 emit(key,doc),减少索引体积;再通过 stale=update_after 策略把视图构建窗口放到凌晨,压缩与碎片整理一次完成,避免白天 IO 争抢。
第三步,流量层:复制链路默认已开 gzip,但国内云主机常把 gzip 级别压到 1,我在 etc/default.ini[httpd] gzip_level = 6跨区流量费用立降 40%;对移动边缘节点,再配 /_replicateselector 只同步增量,首次同步流量压缩后仍可能 500 MB,可拆库到月分片,降低一次性冲击。
最后监控:用 /_node/_local/_systemdisk_sizedata_size 差值,超过 1.5 倍就自动触发 /_compact,通过夜维脚本+企业微信机器人报警,保证压缩收益持续在线。”

拓展思考

如果面试官继续追问“压缩会不会阻塞读写?”,可答:
“CouchDB 的压缩采用 copy-on-write 机制,老文件句柄保持可读,新请求写到新文件,读写零阻塞;但国内云盘 IO 上限 150 MB/s,单库超 500 GB 时压缩会打满,我通过 分库+按租户哈希 把单库控制在 200 GB 以内,同时把 compaction_daemonconcurrency=1 改成 2利用云主机多核红利,把压缩时间窗口从 3 小时压到 40 分钟,业务无感知。”