Kakfa 官方宣称支持事务消息,但是官方的“事务消息”和我们需要的事务消息往往不同。
Kafka 官方事务消息:解决的是在一次事务中需要发送多条消息的情况,保证多个消息之间的事务约束。即多条消息要么都发送成功,要么都发送失败。
RocketMQ事务消息:解决的是本地事务的执行和发消息着两个动作的事务一致性问题。
(资料图片)
我们一般需要的是RocketMQ这种事务消息,如写MySQL和发MQ消息两个动作保证事务性。
Kafka 实现事务消息的思路
通过2PC的方式向Kafka Broker提交消息可以实现事务消息。
通过上图可以看到,生产者启用事务消息后,第一次向Broker发送的是一个半消息,对消费者不可见。只有生产者第二次通知Broker提交消息后,此消息才对消费者可见。而半消息是否提交是由生产者侧的本地事务执行情况决定的。
推演
步骤1 发送半消息 失败 / 超时:消息生产者等待一段时间没有收到Broker的消息可重试。
步骤2 MQ Server 收到消息但回复丢失了:消息生产者可以重试。重试并不会最终在Broker中提交两条相同消息。通过唯一id的方式,可以保证同一条消息即使生产者多次发送在Broker中也只会存在唯一一条记录。
步骤3 本地事务执行失败:MQ 发送方 要求MQ Server丢弃半消息(即步骤4 rollback)。
步骤4 MQ发送方要求MQ Server 提交半消息丢失:MQ Server 超时未收到步骤4的commit / rollback,通过回调接口主动查询本地事务的状态(步骤5 和 步骤6)。