rocketmq分布式事务【yetdone】

https://rocketmq.apache.org/zh/docs/featureBehavior/04transactionmessage/

 

https://zhuanlan.zhihu.com/p/115553176

这张表专门作用于事务状态回查。当提交业务数据时,此表也插入一条数据,它们共处一个本地事务中。通过事务ID查询该表,如果返回记录,则证明本地事务已提交;如果未返回记录,则本地事务可能是未知状态或者是回滚状态。

发送事务消息后,如果消息发送成功,就会调用到这里的executeLocalTransaction方法,来执行本地事务。在这里,它会完成订单数据和事务日志的插入。

那么, checkLocalTransaction 方法就是用于事务状态查询。在这里,我们通过事务ID查询transaction_log这张表,如果可以查询到结果,就提交事务消息;如果没有查询到,就返回未知状态。

注意,这里还涉及到另外一个问题。如果是返回未知状态,RocketMQ Broker服务器会以1分钟的间隔时间不断回查,直至达到事务回查最大检测数,如果超过这个数字还未查询到事务状态,则回滚此消息。

  • 第一次调用createOrder,发送事务消息。如果发送失败,导致报错,则将异常返回,此时不会涉及到任何数据安全。
  • 如果事务消息发送成功,但在执行本地事务时发生异常,那么订单数据和事务日志都不会被保存,因为它们是一个本地事务中。且通知rocketmq回滚
  • 如果执行完本地事务,但未能及时的返回本地事务状态或者返回了未知状态。那么,会由Broker定时回查事务状态,然后根据事务日志表,就可以判断订单是否已完成,并写入到数据库。

基于这些要素,我们可以说,已经保证了订单服务和事务消息的一致性。那么,接下来就是积分服务如何正确的消费订单数据并完成相应的业务操作。

 

消费:

在这里,主要就是对积分数据入库。但注意,入库之前需要先做判断,来达到幂等性消费

如果真的由于特殊原因,消息一直不能被正确处理,那怎么办 ?

第一,重试后发邮件或者短信通知业务方人工介入处理。

第二,进入死信队列。

 

补充:

1 一半的分布式事务,order没回滚

基于MQ的事务仅仅保证的是消息的可靠传递(确保生产者的消息一定可以被消费者接受到),并不保证消费者一定可以处理该消息,如果需要回滚,需要用TCC(我的理解是这样子)

 

2 kafka,下面这个场景会造成数据不一致

本地事务执行不提交

发送消息超时 (网络抖动,发送超时,但是其实已经发送成功)

本地事务回滚

消费者消费消息,造成数据不一致

rocketmq:

2.1

本地事务执行不提交

发送half消息超时 (网络抖动,发送超时,但是其实已经发送成功)

本地事务回滚
通知mq回滚,如果这个通知发送失败,mq多次轮询后超时后也可回滚
 
2.2
本地事务执行不提交
发送half消息,得到ack
本地事务提交
通知mq执行,如果这个包丢了(断网断电),mq多次轮询(多次机会补偿,可以消除偶尔丢包的影响
 
一种方式补偿
1对mybatis做aop,把数据加锁取出来
2处理最后那个commit报文的异常,进而手动或自动处理(像seata at)
https://rocketmq.apache.org/zh/docs/featureBehavior/04transactionmessage/
但要注意 如果使用原连接,则断网不会抛异常,报文commit会进内核,内核发的发的到就不知道
所以使用新连接会更保险点,但要侵入client源码

image

 

 

posted on 2025-07-22 00:04  silyvin  阅读(8)  评论(0)    收藏  举报