如何基于“_changes?since=now”实现连续增量备份?
解读
国内互联网与政企项目普遍要求“RPO≈0”且“可验证恢复”。CouchDB 的 _changes 是官方推荐的增量数据出口,而 since=now 表示“只关心订阅之后的新事件”,天然适合7×24 连续备份场景。
面试官想确认:
- 你是否理解
since=now的长轮询/事件流机制; - 能否把“有序变更流”转成“可重放、可校验、可回退”的备份文件;
- 是否具备生产级异常处理(网络闪断、节点切换、幂等写入、版本升级)。
知识点
- seq 标识符:
last_seq是 CouchDB 内部全局有序的逻辑时钟,不可回退,必须持久化; - feed=continuous:HTTP 会保持chunked 响应,每行一个 JSON,需按行解析;
- heartbeat & timeout:国内云主机常有4 层防火墙 90s 断链,需加
heartbeat=10000&timeout=60000; - include_docs=true:拿到完整 JSON,避免二次回表,但增大 3~5 倍流量,需权衡;
- 幂等落盘:同一 seq 可能因重连重复推送,落盘文件名必须包含 seq 并做已落盘判重;
- 压缩与加密:国内等保 2.0 要求落盘加密,可先
gzip再AES-256-GCM,密钥放 KMS; - 断点续传:进程重启后读取本地checkpoint 文件(
last_seq+node+shard),从该点重新订阅; - 集群故障:多主复制下,同一 doc 在不同节点 seq 不同,备份脚本必须绑定单一节点 VIP 或使用粘性会话,否则 seq 会乱序;
- 版本兼容:CouchDB 3.x 默认开启分区表,
seq格式由整数变为复合字符串,解析时需正则兼容; - 恢复验证:备份集必须定期随机抽样恢复至隔离库,并跑业务回归脚本,满足国内金融合规现场检查要求。
答案
生产级连续增量备份分五步:
-
初始化基线
在业务低峰期用POST /db/_all_docs?include_docs=true全量导出,生成baseline-yyyyMMddHHmmss.gz,记录此时last_seq作为后续增量起点。 -
启动变更流
以常驻进程(Systemd 服务)方式运行:GET /db/_changes?since=<last_seq>&feed=continuous&heartbeat=10000&timeout=60000&include_docs=true使用带重试的 HTTP/1.1 客户端(如 Go 的
github.com/russross/couchdb-changes),设置指数退避最大 180s,防止国内云网络抖动。 -
实时落盘
每收到一行,按seq生成文件{seq}.json.gz,写入本地 NVMe 缓存盘;同一秒批量 fsync,再异步上传至 OSS/S3 冷备桶(国内 Region 选同城冗余存储),对象名带seq前缀,方便点恢复。 -
断点续传
进程优雅退出时把当前已确认 seq 写入/opt/couchdb-backup/checkpoint.db(SQLite 单表,开启 WAL),启动时优先读 checkpoint,避免重复或丢失。 -
周期合并与校验
每日凌晨把 24h 内增量文件合并成incremental-yyyyMMdd.tar.lz4,并计算SM3 摘要(国密算法,国内政务云强制要求),摘要值写入digest.sm3后一起上传。
每月做一次全量+增量恢复演练,随机选一台测试节点清空数据,先还原基线,再按 seq 顺序重放增量,最后跑业务回归脚本,确保RPO≈0且RTO<30min。
拓展思考
- 双活多写场景:若业务采用两地三中心多主,需为每个 vNode 独立维护 seq,避免全局时钟不一致导致备份缺口;
- Serverless 化:可把变更流直接接入阿里云函数计算,每 1000 条触发一次合并上传,实现按量计费,降低夜间低峰成本;
- 合规审计:国内个人信息保护法要求可删除权,备份文件需支持单条 doc 级擦除,可在合并阶段写入布隆过滤器索引,实现秒级定位并重新打包,而不必全量解密;
- 跨版本恢复:CouchDB 4.x 若引入新存储引擎,需提前在测试环境模拟升级,验证旧备份能否向下兼容恢复,防止引擎格式差异导致数据无法回滚。