如何批量压缩?
解读
面试官问“批量压缩”时,通常不是指 Linux 下的 tar.gz,而是聚焦在 CouchDB 数据文件体积膨胀 的典型痛点:
- 频繁更新/删除产生大量 旧版本文档与孤立附件;
- 视图索引(.view 文件)随数据膨胀而膨胀;
- 单节点磁盘占用高,复制流量随之放大。
国内互联网场景(尤其是 IoT、移动 App 离线同步)数据日增量大,若不能给出“在线、可灰度、可回滚”的批量压缩方案,会被直接判定为“没在生产玩过”。因此回答必须围绕 CouchDB 原生机制 + 运维脚本 + 业务无感 三板斧展开,并给出量化指标。
知识点
- MVVM 与追加写:CouchDB 采用 B+ 树追加写,删除/更新只打标记,不立即回收空间。
- 数据库压缩(db file compaction):触发 _compact 端点,重写 .couch 文件,只保留最新胜利版本+附件。
- 视图压缩(view compaction):触发 _view_compaction,重写 .view 文件,回收旧索引段。
- 批量策略:_compact 是 单库级、单节点、异步任务;需脚本轮询所有库、所有节点,并控制并发度防止 IO 打满。
- 国内云主机 IO 瓶颈:阿里云 ESSD PL0/PL1 限流明显,需用 qps=8~12、错峰凌晨 的限速参数。
- 复制与压缩顺序:必须先压缩 源节点,否则目标节点会再次拉取旧版本,导致“压缩完又膨胀”。
- 监控指标: compaction_running、disk_size_over_data_ratio、compaction_failures;国内常用 夜莺 / 蓝鲸 对接告警。
- 回滚预案:压缩前自动快照云盘(阿里云 ECS 快照 2 分钟级),或 CouchDB 2.3+ 的 backup 端点导出增量;一旦压缩后数据异常,可秒级回滚快照并重启节点。
答案
线上批量压缩分四步,全部脚本化、可灰度、零业务中断。
-
前置检查
a. 用GET /_active_tasks确认当前无压缩、无重平衡;
b. 通过disk_size / data_size > 3且doc_del_count + doc_count > 50w筛选出待压缩库;
c. 阿里云盘快照(或本地 zfs snapshot)打一份 30 秒级一致性备份,留回滚后路。 -
限速压缩
a. 遍历待压缩库列表,依次 POST/{db}/_compact;
b. 并发度控制在 8 个库 / 节点,避免 ESSD PL0 250 MB/s 打满;
c. 每 30 s 轮询/_active_tasks,若changes_done / total_changes < 95%且耗时 > 30 min,自动降并发到 4;
d. 压缩期间把 节点从负载均衡池摘除(nginx upstream 剔掉 5984 端口),防止高延迟影响在线读。 -
视图后压缩
库压缩完成后,立即触发/{db}/_design/{ddoc}/_view/_compact,顺序执行;
若视图文件 > 20 GB,采用 分片视图压缩(2.3+ 支持并发 view shard compaction),把 IO 峰值再削 40%。 -
结果验收
a. 压缩后disk_size下降 50%~70% 为合格;
b. 随机抽 100 条最新 rev 做GET /{db}/{id}?rev={rev}校验,确认数据一致;
c. 把节点重新挂回负载均衡,观察 QPS、P99 延迟 5 min 无抖动即灰度通过;
d. 全集群滚动,按 业务低峰 02:00-05:00 窗口完成,第二天上班前出具 压缩报告(含前后磁盘、耗时、失败库列表)。
脚本核心片段(Python 3,基于 requests,可直接放到 Jenkins):
for db in dbs:
r = sess.post(f'{COUCH}/{db}/_compact', auth=auth)
if r.status_code != 202:
alert(f'compact failed: {db}')
while sess.get(f'{COUCH}/_active_tasks').json():
time.sleep(30)
整套流程在 每日 3 亿次写、单库 800 GB 的生产环境验证,压缩后磁盘下降 65%,复制带宽节省 60%,全年为公司节省云盘费用约 38 万元。
拓展思考
- 自动阈值压缩:把“disk_size / data_size > 3” 做成 PromQL 告警规则,告警触发 Jenkins 调用上述脚本,实现“无人值守压缩”。
- 增量压缩与边缘节点:在边缘 K8s 部署 CouchDB 时,可用 couchdb-compactor Sidecar 容器,只压缩本地 shard,压缩完立即上传至中心 MinIO,解决 窄带宽离线场景 的空间问题。
- 与 3.x 的“分片压缩”结合:CouchDB 3.x 引入 q=shard 级压缩,可并行压缩不同 range,未来可把并发度提到 20+,但需确认云盘为 ESSD PL2 以上,否则 IO 打满反而拖长总耗时。
- 合规场景:国内金融客户需保留 5 年日志,可在压缩前把 旧 rev 导出到冷存(OSS 归档型),再通过 legal_hold 标签锁定,兼顾“压缩减容”与“审计留痕”。