如何只上传聚合结果而非原始 10 k 文档?

解读

面试官真正想确认的是:

  1. 你是否理解 CouchDB 离线优先双向同步的设计初衷;
  2. 在带宽敏感、移动端流量计费、合规脱敏等国内真实场景下,如何既保留 CouchDB 的增量同步优势,又避免把 10 k 条明细拖回云端;
  3. 你是否熟悉 CouchDB 的 “文档即最小同步单元” 这一硬性约束,并能在约束内给出工程级方案,而不是简单回答“用视图”。

知识点

  • 文档粒度同步:CouchDB 的 _changes feed 只能整文档同步,无法只传视图或聚合结果。
  • 视图(Map/Reduce):索引在目标端构建,不减少传输量
  • 过滤复制(filter function):可跳过不需要的文档,但不能改变文档内容
  • 更新处理器(update handler):服务端原地改写文档,可用于预聚合
  • 数据库拆分(db-per-service / db-per-user):国内大厂常用,把聚合结果写进独立库,再对该库做同步。
  • 外部作业层:用 Kafka-Flink、Spark、Node.js 定时任务 在本地先算好聚合,再 PUT 一条结果文档。
  • _local 文档:不参与同步,可存中间状态,避免重复计算
  • 国内云厂商限制:如阿里云 CouchDB 版对 单文档 8 MB单库 20 GB 的硬性上限,必须控制结果文档大小。
  • 等保与《个人信息保护法》:原始明细若含敏感字段,不能出本地机房,必须脱敏或聚合后才能上传。

答案

分三步落地,既遵守 CouchDB 机制,又满足国内合规与带宽限制:

  1. 本地预聚合
    在边缘节点(Android、IoT 网关或门店服务器)用 PouchDB/Cloudant-Sync 先读取 10 k 条本地文档,通过 Map/Reduce 或 JavaScript 聚合脚本 算出指标(如销售额、库存总量)。
    把聚合结果写成一条新文档:

    {
      "_id": "agg_20250618_001",
      "type": "daily_sales",
      "amount": 12345.67,
      "count": 10,
      "storeId": "sh001",
      "timestamp": "2025-06-18T14:00:00+08:00"
    }
    
  2. 隔离上传通道
    创建独立数据库 sales_agg,只放聚合文档;原始明细库 sales_raw 标记 "do_not_replicate" 或使用 过滤函数 return false; 禁止上传。
    sales_agg 开启单向复制到云端,带宽瞬间降到 1/10 k

  3. 云端消费与回写
    云端监听 sales_agg 的 _changes,触发后续业务(BI 报表、预警)。
    若总部需要下推配置,用 separate config db 反向同步,不触碰原始明细,实现“上行只传结果、下行只传指令”的干净通道。

一句话总结:把聚合动作下沉到本地,把 CouchDB 的“文档”变成“聚合结果”,再让复制只关心这条结果文档。

拓展思考

  • 如果聚合维度动态变化(如突然按小时变按分钟),如何让 聚合代码热更新 而不断网?
    可把聚合脚本做成 attachment 存于 _design/agg 文档,利用 CouchDB 自身的同步机制下发新版本,边缘节点定时重载。

  • 当边缘节点算力不足,能否用 云边协同
    国内运营商已推 5G MEC,可把轻量 Flink 任务部署到 MEC 节点,CouchDB 通过 changes feed 把增量推给 MEC,算完再写回 agg 库,既省终端电量又满足低时延。

  • 若集团审计突然要求“回溯原始 10 k 条”,而本地已清理,如何补救?
    提前在本地把原始数据 加密打包成 blob,存到 对象存储(OSS、COS),只在 CouchDB 里保留 外链与哈希。审计时走内网拉取,平时不同步,用时可验证,兼顾合规与带宽。