安然写字的地方

事务消息

事务消息

消息中间件提供事务消息功能,即从mq的角度出发,保证一个本地事务和消息发送结果的最终一致性。

遵循base协议

kafka 多分区、持久化保证消息不丢失 消费端 重试+死信功能,保证消息一定被消费完成 事务协调器,回查producer,保证事务状态最终一致(commit or rollback) 以上三点,保证执行本地事务和消息最终被消费完成的最终一致性

Kafka实现方案

db实现方案

生产者

  1. 本地事务执行时多写一条记录 记录消息发送的状态
  2. 发消息到消息中间件,如果成功,更新消息状态为已发送
  3. 定时脚本扫码读取未发送完成的消息,发送到消息中间件

注意:第二步中,如果发消息到中间件成功,但消息未更新成已发送,同时脚本也扫描到了,消息就会重复发送,这里需要保证消息者消费消息幂等

消费者

  1. 消费者业务幂等实现处理,是通过对记录表的记录判重来实现 实现幂等的方式有很多种,悲观锁,乐观锁,分布式锁

注意点

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、异步提交事务,事务完整性通过回查机制得到保证(保证消息发送和事务执行的原子性)。

参考资料