事务消息
事务消息
消息中间件提供事务消息功能,即从mq的角度出发,保证一个本地事务和消息发送结果的最终一致性。
遵循base协议
kafka 多分区、持久化保证消息不丢失 消费端 重试+死信功能,保证消息一定被消费完成 事务协调器,回查producer,保证事务状态最终一致(commit or rollback) 以上三点,保证执行本地事务和消息最终被消费完成的最终一致性
Kafka实现方案
db实现方案
生产者
- 本地事务执行时多写一条记录 记录消息发送的状态
- 发消息到消息中间件,如果成功,更新消息状态为已发送
- 定时脚本扫码读取未发送完成的消息,发送到消息中间件
注意:第二步中,如果发消息到中间件成功,但消息未更新成已发送,同时脚本也扫描到了,消息就会重复发送,这里需要保证消息者消费消息幂等
消费者
- 消费者业务幂等实现处理,是通过对记录表的记录判重来实现 实现幂等的方式有很多种,悲观锁,乐观锁,分布式锁
注意点
1、需要将消息状态和消息发送情况同时记录到db中 2、业务需要单独开发定时任务功能,并且更新db中消息发送状态 软状态 + 补偿
RocketMQ实现方案
RocketMQ事务消息设计则主要是为了解决Producer端的消息发送与本地事务执行的一致性问题
整体流程:
发送prepare(half) 消息
执行本地事务
commit or rollback
内部具体实现流程:
1、生产者提交half消息,broker将消息插入commitlog,返回offset给producer; 2、生产者执行本地事务; 3、根据本地事务执行结果,发送commit or rollback请求到服务端,服务端根据请求处理half消息的提交或回滚(即将消息写到consumeGroup还是丢弃) 注意,如果客户端执行第三步失败,服务端有回查客户端机制,确保事务消息成功结束,保证事务完整性。
试用场景:
帮助用户实现类似 X/Open XA 的分布事务功能,通过 MQ 事务消息能达到分布式事务的最终一致; X/Open XA是典型的二阶段提交,由AP TM RM组成,rocketmq producer同时实现了AP 和 TM的角色,同时broker的回查机制也提供了TM的角色; 回查机制实际上也会一种补偿机制,保证本地事务和发消息结果最终一致(要么都成功要么都失败)。
总结:
1、rocketmq事务是session内的,且一次事务内只支持发送单条消息; 2、没有通过显示start或者select开启事务,half消息本身包括开启事务的语义,相比于rabbitmq减少了一次网络交互; 3、异步提交事务,事务完整性通过回查机制得到保证(保证消息发送和事务执行的原子性)。