如何降低索引频率到每 6 小时一次?

解读

面试官问“降低索引频率到每 6 小时一次”,并不是让你把索引删掉,而是考察你对 CouchDB 视图(View)增量更新机制外部触发策略 的理解。
国内线上环境普遍采用 “大集群 + 高频写入” 模式,如果每次查询都触发 stale=update_after,索引 CPU 抢占会拖慢读写。
因此,企业通常把视图索引做成 定时批处理,每 6 小时统一更新一次,既保证数据一致性,又节约资源。
回答时要明确两点:

  1. CouchDB 本身 没有 cron,必须用外部调度;
  2. 要让查询 不触发索引,必须主动带 stale=okstale=update_after 参数,并配合 读写分离 架构。

知识点

  1. 视图索引时机:CouchDB 采用 B+Tree 增量索引,只有当下一次带 stale=false(默认)的查询到达时才会重新计算;
  2. stale 参数三策略
    • stale=ok —— 直接返回上次结果,绝对不触发索引
    • stale=update_after —— 立即返回旧结果,后台异步触发一次索引
    • 默认(无 stale)—— 同步阻塞,等索引完成才返回。
  3. 外部调度:生产环境用 crontabK8s CronJob 每 6 小时跑一次 curl -X GET http://localhost:5984/db/_design/ddoc/_view/view?stale=false,强制刷新;
  4. 集群场景:国内多云部署时,通常 指定一个“索引节点” 负责定时刷新,其余节点对外提供 stale=ok 查询,避免重复计算;
  5. 监控指标:通过 /_node/<name>/_system 观察 view_index reductionscpu_time,确保 6 小时窗口内索引耗时 < 业务低峰期时长。

答案

线上要把索引频率降到每 6 小时一次,分三步落地:
第一步,所有在线查询强制带 stale=ok,确保用户请求不再触发实时索引;
第二步,在 运维层 加一条 crontab(或 K8s CronJob):
0 */6 * * * curl -X GET http://localhost:5984/db/_design/ddoc/_view/view?stale=false -u user:pass
这条命令每 6 小时主动访问一次视图,强制 CouchDB 在低峰期完成增量索引
第三步,读写分离:把上述 cron 放在专用“索引节点”上执行,其他节点继续对外提供 stale=ok 查询,既降低集群负载,又保证数据 6 小时内必更新一次。
如需更细粒度,可在 cron 脚本里先判断 doc_count 变化量,若无新增文档则跳过本次索引,进一步节省 CPU。

拓展思考

  1. 如果业务方 不能接受 6 小时延迟,可引入 双视图策略
    • 热视图:关键维度用 stale=update_after,保证 1 分钟内收敛;
    • 冷视图:全量统计用上述 6 小时 cron,降低开销。
  2. 政务内网 等离线场景,可把 cron 做成 U 盘触发:运维人员每 6 小时手工插盘执行脚本,既满足保密要求,又实现“准实时”索引。
  3. 未来升级到 CouchDB 4.x 后,可试用 “视图分片索引” 预览功能,把索引任务拆到不同分片并行执行,进一步缩短 6 小时窗口内的单次耗时。