如何错峰?
解读
在国内 CouchDB 面试中,“错峰”并不是让数据库“避开早晚高峰”,而是指在分布式、多主复制的场景下,如何降低节点间写冲突、复制风暴与磁盘 I/O 峰值,从而保障集群 7×24 小时平稳运行。面试官想听你能否把“错峰”拆解成写流量削峰、复制流量削峰、磁盘合并削峰三层,并结合 CouchDB 的 B+ 树追加写、MVCC、视图增量更新、复制调度等机制给出可落地的国内生产级方案。
知识点
- 写流量削峰:_bulk_docs 批量大小、delayed_commits 权衡、w=quorum 与 w=1 的 SLA 分级。
- 复制流量削峰:_replicator 数据库的连续/调度模式、worker 与 connection 参数、国内跨可用区带宽成本模型。
- 视图构建削峰:stale=update_after、自定义 filter 函数、设计文档分桶拆库。
- Compaction 削峰:分段式 compaction(monitor + POST /{db}/_compact 脚本)、国内云盘“Burst IO”额度耗尽场景下的限速策略。
- 国内云厂商限制:单盘 2 万 IOPS 封顶、跨可用区流量 0.8 元/GB、凌晨 2-6 点带宽富余窗口。
答案
“错峰”在 CouchDB 里分三步落地:
第一步,写流量错峰。业务侧把高峰 1 万 QPS 的随机单条写改为内存队列 + 200 ms 窗口聚合,通过 _bulk_docs 每批 500 条、delayed_commits=true 的方式落盘,可把每秒 1 万次 fsync 降到 200 次,磁盘 util 从 90% 降到 30%;对账类请求用 w=1 快速返回,订单类请求用 w=quorum 保证一致,实现 SLA 分级。
第二步,复制流量错峰。国内三可用区部署,白天业务高峰时把 _replicator 的 connection=2、worker=1,主动降级复制带宽到 20 Mbps,优先保障用户读写;凌晨 2-6 点带宽富余窗口,通过 Crontab 调用 _replicator 把 connection=10、worker=4,把积压 50 GB 增量数据在 4 小时内追平,避开跨区 0.8 元/GB 的峰值计费。
第三步,Compaction 与视图错峰。设计文档按租户拆分为 32 个库,每个库<100 GB,监控 _active_tasks 当 compaction 磁盘 IO>30% 时立即调用 DELETE /{db}/_compact 取消任务;视图采用 stale=update_after,并在凌晨 3 点统一触发 _view_cleanup,利用云盘 Burst 余额未耗尽时段完成 30 个视图的增量更新,避免白天查询 502。
通过“写-复制-磁盘”三层错峰,我们把双十一峰值 TPS 从 1.2 万提升到 2 万,P99 延迟仍稳定在 200 ms 以内,跨区流量成本下降 42%,全年零因 IO 打满导致的可用区切换。
拓展思考
- 如果业务必须 24 小时强一致,能否用区域感知型负载均衡(读本地、写 quorum 跨区)替代“凌晨集中复制”?代价是白天跨区写流量翻倍,需评估 0.8 元/GB 是否可接受。
- 国内部分金融项目要求双活+零 RPO,可把 CouchDB 的节点级写限流插件(couchdb-limiter)与Kafka 顺序写队列结合,实现“削峰不丢单”,但会增加 15 ms 平均延迟。
- 未来升级到 CouchDB 4.x 的分片集群后,错峰策略需把“库级复制”细化到“分片级复制”,并引入分片迁移窗口与Rebalance 限速,否则跨分片热点仍会把磁盘 IO 重新打满。