如何基于“_changes?since=now”实现连续增量备份?

解读

国内互联网与政企项目普遍要求“RPO≈0”且“可验证恢复”。CouchDB 的 _changes 是官方推荐的增量数据出口,而 since=now 表示“只关心订阅之后的新事件”,天然适合7×24 连续备份场景。
面试官想确认:

  1. 你是否理解 since=now长轮询/事件流机制;
  2. 能否把“有序变更流”转成“可重放、可校验、可回退”的备份文件;
  3. 是否具备生产级异常处理(网络闪断、节点切换、幂等写入、版本升级)。

知识点

  • 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 要求落盘加密,可先 gzipAES-256-GCM,密钥放 KMS;
  • 断点续传:进程重启后读取本地checkpoint 文件last_seq+node+shard),从该点重新订阅;
  • 集群故障:多主复制下,同一 doc 在不同节点 seq 不同,备份脚本必须绑定单一节点 VIP 或使用粘性会话,否则 seq 会乱序;
  • 版本兼容:CouchDB 3.x 默认开启分区表seq 格式由整数变为复合字符串,解析时需正则兼容
  • 恢复验证:备份集必须定期随机抽样恢复至隔离库,并跑业务回归脚本,满足国内金融合规现场检查要求。

答案

生产级连续增量备份分五步:

  1. 初始化基线
    在业务低峰期用 POST /db/_all_docs?include_docs=true 全量导出,生成 baseline-yyyyMMddHHmmss.gz,记录此时 last_seq 作为后续增量起点。

  2. 启动变更流
    常驻进程(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,防止国内云网络抖动。

  3. 实时落盘
    每收到一行,按 seq 生成文件 {seq}.json.gz,写入本地 NVMe 缓存盘;同一秒批量 fsync,再异步上传至 OSS/S3 冷备桶(国内 Region 选同城冗余存储),对象名带 seq 前缀,方便点恢复

  4. 断点续传
    进程优雅退出时把当前已确认 seq 写入 /opt/couchdb-backup/checkpoint.db(SQLite 单表,开启 WAL),启动时优先读 checkpoint,避免重复或丢失

  5. 周期合并与校验
    每日凌晨把 24h 内增量文件合并成 incremental-yyyyMMdd.tar.lz4,并计算SM3 摘要(国密算法,国内政务云强制要求),摘要值写入 digest.sm3 后一起上传。
    每月做一次全量+增量恢复演练,随机选一台测试节点清空数据,先还原基线,再按 seq 顺序重放增量,最后跑业务回归脚本,确保RPO≈0RTO<30min

拓展思考

  • 双活多写场景:若业务采用两地三中心多主,需为每个 vNode 独立维护 seq,避免全局时钟不一致导致备份缺口;
  • Serverless 化:可把变更流直接接入阿里云函数计算,每 1000 条触发一次合并上传,实现按量计费,降低夜间低峰成本;
  • 合规审计:国内个人信息保护法要求可删除权,备份文件需支持单条 doc 级擦除,可在合并阶段写入布隆过滤器索引,实现秒级定位并重新打包,而不必全量解密;
  • 跨版本恢复:CouchDB 4.x 若引入新存储引擎,需提前在测试环境模拟升级,验证旧备份能否向下兼容恢复,防止引擎格式差异导致数据无法回滚