第 6 / 19 篇

第 5 章 用订单号理解 Key 和分区

建立三个分区的主题

bin/kafka-topics.sh --bootstrap-server localhost:9092 \
  --create --topic orders \
  --partitions 3 --replication-factor 1

接着启动带 Key 的生产者:

bin/kafka-console-producer.sh --bootstrap-server localhost:9092 \
  --topic orders \
  --property parse.key=true \
  --property key.separator='|'

输入以下三行,注意每行中间的 |:

A1001|{"event_id":"e-001","order_id":"A1001","type":"OrderCreated","amount_fen":9900,"schema_version":1}
A1002|{"event_id":"e-002","order_id":"A1002","type":"OrderCreated","amount_fen":2000,"schema_version":1}
A1001|{"event_id":"e-003","order_id":"A1001","type":"OrderPaid","amount_fen":9900,"schema_version":1}

左边是 Key,右边是 Value。金额用“分”的整数表示,避免用二进制浮点数直接表示钱。event_id 标识一次业务事件,order_id 标识一笔订单,两者用途不同。

显示记录位置

bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 \
  --topic orders --from-beginning --group orders-inspect-v1 \
  --property print.key=true \
  --property print.partition=true \
  --property print.offset=true

你应看到分区、偏移量、Key 和 JSON。观察 A1001 的两个事件:在本书默认分区策略和未改分区数时,它们进入同一分区,偏移量按追加顺序增大。不同订单也可能落入同一分区,Key 与分区不是一对一关系。

不能依赖屏幕显示的三行恰好是发送时的全局顺序,因为消费者从多个分区取数据。也不要背下“A1001 一定进分区几”,分区映射不是业务规则。

业务顺序还有额外条件

把同一订单作为 Key 只是基础。若两个生产者同时写同一订单,“谁先发生”的业务顺序仍需要由上游协调,或者在事件里带业务版本号。消费者若并行处理同一分区,也要保证同一订单的处理顺序。

新增分区可以增加并行度,但可能改变 Key 映射。需要严格保持历史与后续顺序时,应先设计迁移和切换方案,而不是在高峰时随手扩分区。

练习:把 A1001 改成固定 Key all-orders 会怎样?所有这些消息会集中到同一个分区,失去按订单分摊流量的优势。