当文档历史超过 1000 个版本时,如何触发“compact”以缩减元数据?
解读
面试官真正想考察的是你对 CouchDB MVCC(多版本并发控制)机制与数据库文件膨胀之间关系的理解,以及你是否能在国内常见的“离线优先+移动同步”场景下,主动用运维手段或代码策略把历史版本数降下来。
“1000 个版本”并非官方硬编码阈值,而是国内很多落地项目把 revs_limit 调到 1000 后,发现 .couch 文件暴涨、同步流量陡增的经验临界点。因此,回答必须同时覆盖“调参”和“触发压缩”两条线,并给出可落地的脚本或定时任务方案。
知识点
- MVCC 与 revs_tree:每次更新都追加一个新版本,旧版本仍在文件里,直到压缩。
- revs_limit:单文档保留的最大版本深度,默认 1000;调小可直接减少历史。
- 压缩(compaction):把旧版本、已删除的文档和视图的旧索引一并清理,生成新的
.couch文件并原子切换。 - 触发方式:
- HTTP POST /{db}/_compact(需管理员权限)
- couchdb -c 命令行(单机版)
- 调度器:
_scheduler/compaction(2.x+ 版本自带,可配 cron 表达式)
- 国内云厂商限制:阿里云、腾讯云托管版 CouchDB 通常关闭外部 _compact 权限,需提工单或在控制台勾选“自动压缩”。
- 移动同步场景:PouchDB 默认
revs_limit: 1000,若业务方频繁更新,手机端 DB 体积先爆炸,需在网关层提前压缩并下调 revs_limit 到 50~100。
答案
分三步走,线上无中断完成:
- 调小 revs_limit(提前削顶)
这一步立即生效,但旧版本仍占磁盘。curl -X PUT http://admin:pass@localhost:5984/your_db/_revs_limit -d '100' - 触发数据库压缩(真正释放空间)
返回curl -X POST http://admin:pass@localhost:5984/your_db/_compact \ -H "Content-Type: application/json"{"ok":true}后,CouchDB 会在后台线程执行;可通过GET /_active_tasks观察进度。 - 国内生产环境自动化
- 自建集群:在
local.ini里打开[compactions]段,写一条
并配_default = [{db_fragmentation, "70%"}, {view_fragmentation, "60%"}, {parallel_view_compaction, true}]cron = 0 2 * * *每天凌晨 2 点自动检查。 - 托管版:若云厂商屏蔽 API,把步骤 1 的
revs_limit降到 50~100,然后提交工单申请“后台压缩”,一般 1 h 内完成。
- 自建集群:在
注意:压缩期间磁盘需预留 2×当前库大小的剩余空间,国内 SSD 云盘成本敏感,务必提前扩容。
拓展思考
- “1000”不是银弹:国内某物流 APP 把 revs_limit 设成 30,配合每日自动压缩,一年节省 62% 存储费用,移动端同步流量下降 45%。
- 分片集群下的压缩顺序:BigCouch 或 3.x 集群先压缩各分片副本,再压缩视图;若副本正在同步,压缩会自动重试,但会拉长窗口,需在 SLA 里预留 30 min 抖动。
- 与备份的权衡:压缩后旧版本永久消失,若业务需审计回溯,可在压缩前用
couchbackup做一次增量快照到 OSS,国内合规场景常用。