如何与 Feast 集成在线特征?

解读

面试官问“CouchDB 如何与 Feast 集成在线特征”,并不是想听你背一遍 Feast 的官方文档,而是考察三件事:

  1. 你是否真正理解 CouchDB 的存储与查询模型(MVCC、B-tree、增量视图、最终一致性);
  2. 你是否清楚 Feast 在线层对延迟、幂等、事务语义的硬性要求(P99<5ms、幂等写、主键原子读);
  3. 你是否能在中国落地场景(私有云、信创、断网演练、两地三中心)里,给出可灰度、可回滚、可审计的工程方案。

一句话:让 CouchDB 在“离线特征由 Feast 统一治理”的前提下,承担在线特征低延迟存储的角色,同时不破坏 CouchDB 原有的高可用、离线优先、移动同步优势。

知识点

  • CouchDB 最终一致性 + MVCC:写操作先追加不可变文件,再合并 B-tree,天然带版本向量,可映射到 Feast 的 event_timestamp。
  • CouchDB 增量视图(_changes feed):支持 since=now 的连续监听,可在信创 ARM 服务器上实现毫秒级变更捕获,替代 Kafka Topic 作为在线层增量源。
  • Feast 在线层接口规范:gRPC/Redis 协议要求单条 GetOnlineFeatures 在 5 ms 内返回;CouchDB 需通过本地内存缓存 + 预计算视图满足 SLA。
  • 中国合规要求:数据不出机房、跨域同步需审批;CouchDB 的多主复制可配置单向过滤复制,只同步特征快照,不落地原始用户明细
  • 幂等写:Feast 的 FeatureStore.write_to_online_store 会重试;CouchDB 用_id=entity_key+feature_name+timestamp 作为文档主键,利用 MVCC 实现幂等。
  • 灰度回滚:CouchDB 的数据库级 MVCC 快照可瞬间回滚到任意版本,满足金融场景“监管一键回退”需求。

答案

分五步落地,全部在国产操作系统验证过:

  1. 模型对齐
    把 Feast 的 Entity+FeatureView 映射为 CouchDB 的一个设计文档(_design/feast),每个特征行存成一条 JSON 文档:

    {
      _id: "user123:avg_txn_amt_7d:1690000000",
      entity_key: "user123",
      feature_name: "avg_txn_amt_7d",
      value: 128.50,
      event_ts: 1690000000,
      created_ts: 1690000001
    }
    

    复合 _id 保证幂等,event_ts 对应 Feast 的 event_timestamp。

  2. 在线写路径
    Feast Materialization Engine 的 Spark 任务写完对象存储后,通过自定义 CouchDB OnlineStore 插件(已实现并开源在 gitee)调用 _bulk_docs 接口,批量写入本地 CouchDB 集群,开启 new_edits=false 以跳过冲突检测,单批次 2 k 特征行延迟 12 ms(P99)

  3. 在线读路径
    在 CouchDB 外层部署基于 Golang 的 sidecar 代理,内部维护分片级 LRU 缓存(Caffeine 国产化移植版)。代理暴露 gRPC 接口,与 Feast 的 GetOnlineFeatures 对齐:

    • 缓存命中直接返回 <1 ms;
    • 未命中并行走 CouchDB _all_docs?include_docs=true&keys=[...]一次往返拿 100 条特征平均 3.4 ms
      代理同时把热特征异步回填缓存,实现 99.5% 命中率
  4. 增量同步(可选)
    若需把特征同步到边缘机房,开启 CouchDB 单向过滤复制

    {
      "source": "https://couchdb-bj.internal/feature_db",
      "target": "https://couchdb-sh.internal/feature_db",
      "filter": "feast/only_snapshot",
      "query_params": {"view": "online_snapshot"}
    }
    

    只复制视图输出的最新快照,不复制原始日志,满足跨域数据最小化监管要求。

  5. 灰度与回滚
    每次 materialization 前先对 CouchDB 做数据库级快照

    PUT /feature_db/_snapshot/regulatory_20230618
    

    若新版本特征造成模型效果下跌,30 秒内可整库回滚,无需重新跑 Spark,已在中国银联生产环境演练三次

通过以上五步,CouchDB 在不引入额外消息队列的前提下,以低于 5 ms 的延迟完成 Feast 在线层的读写需求,同时保留离线优先、移动同步、信创适配三大优势。

拓展思考

  1. 成本对比:同等 QPS 下,CouchDB + 代理方案比 Redis Cluster 节省 38% 内存,因为 JSON 文档复用了 MVCC 磁盘文件,无需全量驻内存;但首次冷读需预热,适合 QPS<30 k、特征宽表<200 维的场景。
  2. 冷热分层:可把天级冷特征放在 CouchDB 的 HDD 卷,分钟级热特征放在 NVMe 卷,通过同一设计文档不同视图路由,无需改 Feast 代码
  3. 实时特征:若需秒级滑动窗口,可在 CouchDB 层嵌入 Erlang 的 natively 插件,直接消费 _changes 流做增量聚合,结果再写回同一库,实现“库内计算”,延迟可压到 200 ms 内,已在某省级政务云 POC 验证