一粟 · yisu.app
· 12 min read
kafka架构

把 Kafka 用成数据库的边界与代价

Kafka 用 log compaction + KTable 可以做"事件数据库",但代价是什么?什么时候该用,什么时候不该用,本文给出一份边界图。

"用 Kafka 当数据库"是流式架构里最容易被滥用的模式。Log compaction 让 Kafka 可以保留每个 key 的最新值,KTable 让消费端可以"查询当前状态"——听起来这就是个数据库。但真做生产业务,会发现它有非常具体的边界。本文把这些边界拆开讲。

什么是"把 Kafka 当数据库"

典型模式是这样的:

  1. 所有状态变更写到一个 Kafka topic(compacted)。
  2. 每个变更包含 key + value,key 是实体 ID。
  3. 消费端启动时从头消费,重建出"当前状态"(KTable)。
  4. 查询走 KTable,不查外部数据库。

这个模式看起来很美:单系统、事件溯源、天然审计。但它有几个边界。

边界一:查询模式

KTable 只支持按 key 查询。如果你的查询是"查所有余额大于 1000 的账户",Kafka 没法做。需要:

  • 另起一个 topic 做索引(按余额排序)。
  • 把 KTable 物化到 RocksDB,用 RocksDB 查。
  • 或者把数据再同步到 Elasticsearch / Redis。

无论哪种,都已经不是"Kafka 当数据库"了,而是"Kafka + 别的数据库"。

把 Kafka 当数据库的第一个边界:你的查询是不是只有 by-key?如果不是,就需要第二个系统。

边界二:重建成本

KTable 启动时要从头消费 topic 重建状态。topic 有 100 亿条记录时,重建要几小时。这意味着:

  • 消费者扩容很慢。
  • 故障切换很慢。
  • 开发迭代很慢(每次重启都要等)。

Kafka Streams 的 state store 用 RocksDB 做本地存储 + changelog topic,部分解决了这个问题。但代价是每个 consumer 都要本地存一份"状态",磁盘与内存开销线性增长。

边界三:一致性模型

Kafka 是"at-least-once"或"exactly-once"(EOS)。但 EOS 只在 Kafka 内部成立——一旦和外部系统交互,就需要幂等 + 事务。

把 Kafka 当数据库意味着"没有事务跨 Kafka 与外部系统"。比如"写 Kafka + 写 Redis"是没法原子化的,只能用 outbox pattern 模拟。这比想象中复杂。

边界四:成本

Kafka 的存储成本不低。同等数据量,Kafka 比 MySQL 贵 3–5 倍。原因:

  • Kafka 默认 3 副本。
  • Kafka 不压缩(虽然支持 zstd 但默认未开)。
  • Kafka 的存储按 partition 分,小 partition 浪费大。

把 10TB 的"状态数据"放 Kafka,每月成本可能比放 Postgres 高一个量级。

边界五:延迟

Kafka 的查询延迟是"消费延迟"——从消息写入到 KTable 看到的时间。通常 100ms–1s。这对实时业务够用,但对"读你刚写的"场景就不够。比如用户下单后立刻查订单状态,KTable 可能还没消费到。需要 read-your-write 一致性的场景,Kafka 当数据库不合适。

什么时候"用 Kafka 当数据库"是合适的

场景是否合适原因
审计日志合适天然事件溯源
用户画像合适by-key 查询、可重建
订单系统不合适需要事务、复杂查询
实时计数合适追加写、聚合读
账户余额不合适需要 read-your-write
配置中心合适by-key、变更通知

"事件溯源 + 物化视图"才是正解

真正工程化的做法是"事件溯源 + 物化视图":

  • Kafka 存事件流(source of truth)。
  • 消费端把事件物化到 Postgres / Redis / Elasticsearch。
  • 查询走物化视图。

这种模式保留了"事件溯源"的好处(审计、回放),又避开了 Kafka 当数据库的边界。代价是物化视图的同步延迟与一致性维护成本。

几个工程实践

  • 用 log compaction 减少冷数据,但别期待它当数据库。
  • 用 Kafka Streams 的 state store 做轻量 KTable,但限制规模在 100GB 内。
  • 规模超过 100GB 或需要复杂查询,立刻接外部数据库。
  • read-your-write 场景永远走外部数据库。

给团队的简短建议

  • 把 Kafka 当数据库前,先回答四个问题:查询模式、重建成本、一致性、延迟。
  • 有任一不满足,立刻改方案。
  • "事件溯源 + 物化视图"是更通用的解。

Kafka 是个好工具,但它不是数据库。把它的边界看清楚,才能用对地方。