如何校验迁移后文档数量与哈希一致性?

解读

在国内金融、政务、医疗等对数据零丢失零容忍的场景里,**“迁移后文档数量与哈希一致性”**是上线评审的硬门槛。面试官想确认候选人能否:

  1. 用 CouchDB 原生工具低成本完成全量校验;
  2. 不停机条件下解决“源端持续写入”带来的漂移;
  3. 给出可审计的量化报告,满足国内等保、银监、信创验收要求。

知识点

  • CouchDB 序列号(update_seq):每个数据库单调递增,可快速判断“源库是否又写入”。
  • _all_docs 与 _changes 的差异化:前者只能拿到最新修订,后者能拿到历史删除标记,必须组合使用才能算准“逻辑文档数”。
  • MVCC 修订号(_rev):同一 id 下不同世代,不能直接用于跨库哈希,需先归一化。
  • Erlang 视图 Server 的 reduce 溢出:国内 4 亿条记录规模下,若 reduce 阶段返回巨大数组,默认会触发“reduce_overflow_error”,必须改用 built-in _count 或 list 函数
  • 国内信创环境常见 ARM+麒麟组合,openssl 版本低,sha256sum 性能只有 x86 的 40%,需提前评估耗时。

答案

分五步落地,全部脚本用官方接口,无需第三方插件,可直接写进验收报告。

  1. 冻结写入窗口
    若业务允许,在源库执行 PUT /{db}/_security 把写账号临时摘除;若不允许,则记录迁移开始时的 update_seq 作为“一致性锚点”,后续用 _changes?since=锚点 把增量补到目标库,再校验。

  2. 计算源库“逻辑文档数”
    POST /{db}/_all_docs?limit=1 先取 total_rows,再 POST /{db}/_changes?descending=true&limit=1 拿到最后一条删除标记的 seq,两者相减得到真实存活文档数,写入《迁移报告》第一行。

  3. 生成源库“内容哈希”
    设计视图:

    map: function (doc) { emit(doc._id, doc._rev); }
    reduce: _count
    

    再建第二个视图:

    map: function (doc) { emit(null, require('crypto').createHash('sha256').update(JSON.stringify(doc, Object.keys(doc).sort())).digest('hex')); }
    reduce: function (keys, values) { return values.sort().join(''); }
    

    对 4 亿条记录,用 ?group_level=0 直接取 reduce 结果,得到 64 位十六进制摘要,耗时约 3 分钟(16 核信创服务器)。把摘要写入报告第二行。

  4. 目标库执行完全相同的 2、3 步
    拿到目标库的“逻辑文档数”与“内容哈希”,与源库逐字节比对。若一致,进入第 5 步;若不一致,用 diff _changes 法快速定位差异 id,再人工修复。

  5. 出具“双章”报告
    报告里必须包含:

    • 源、目标库的 URL、节点 IP、CouchDB 版本、Erlang 版本;
    • 校验时刻的 update_seq 截图;
    • 两份哈希的十六进制字符串执行耗时
    • DBA 与业务方双方签字,满足国内等保 2.0 对“数据迁移可追溯”条款。

拓展思考

  • 增量漂移场景:若业务 7×24 写入,可在第 1 步后启动 _changes?feed=continuous&since=锚点 把增量写入 Kafka,目标库消费完后再做一次“二次哈希”,实现热迁移零窗口
  • 分片集群:国内大型互联网用 CouchDB 3.x 做分片,校验时要逐分片执行上述流程,再把各分片哈希再做一次 Merkle Tree,防止“跨分片碰撞”。
  • 合规加密:部分政务云要求哈希算法用国密 SM3,只需把视图里的 crypto.createHash('sha256') 换成 sm3(),Node 端提前安装 @npm/sm-crypto 即可,无需改 CouchDB 源码
  • 自动化回归:把五步脚本封装成 Jenkins 流水线,每次版本升级后自动跑一遍,10 分钟内给出“数据零丢失”报告,可成为团队 CI/CD 的强制门禁。