同一个订单的创建、支付、取消消息必须有序,你会怎么设计分区和消费逻辑?
我的判断
同一订单要有序,就用 orderId 作为消息 key,让相关事件进入同一分区,再由单分区串行消费并用状态机抵抗重试与乱序。
生产者发布创建、支付、取消事件时都设置同一个 orderId key,Kafka 的分区器会把它们放到同一分区,分区内有序。消费组内这个分区只由一个实例处理,不能把同一分区消息随意扔到并发线程池后失去顺序。
但链路仍可能出现业务乱序:不同上游各自发消息、失败重试、历史回放。事件会带订单版本或状态序号,消费者只接受合法迁移:
CREATED(v1) -> PAID(v2) -> SHIPPED(v3)
收到未来版本时可短暂缓冲或重试,收到旧版本直接幂等忽略;长期缺版本要告警并查源数据。
增加分区时,默认 hash 结果可能变化,同一 key 的新旧消息短期落不同分区。核心有序 Topic 扩分区前要评估生产切换、旧消息清空或版本隔离,不能在线直接加完就结束。
容易答偏踩坑误区
- 全 Topic 只建一个分区。 能保全局顺序,但吞吐和可用性代价过大。
- 按消息类型做 key。 同一订单的创建和支付会去不同分区。
- 分区内消费后再无序并发处理。 Kafka 顺序会在应用层被打破。