此处就不介绍分布式事物的概念了,分布式事物主要有三种方法 2pc、3pc、tcc、最终消息一致性
2pc
2pc即两段式提交
第一阶段:
资源管理者rm向各资源参与者发送 prepare 消息,各参与者执行本地事物 写 redo,undo日志,但不提交
参与者commit事物
3pc
3pc引入超时机制
在网络故障导致超时情况下,参与者会默认执行commit。
所以3pc存在的缺点 是 如果有某一个参与者 返回失败,则该故障的参与者无法收到abort,commit事物,会导致数据不一致。
tcc
tcc由支付宝提出,是一个应用层面的2pc
详见 https://www.liangzl.com/get-article-detail-525.html
最终消息一致性
详细可见这篇文章 https://blog.youkuaiyun.com/daijiguo/article/details/89059963
1、producer 发送事物消息到 broker,broker将该事物消息设置为不可见
2、producer执行本地事物
3、发送确认消息到broker,有三个返回值
LocalTransactionState.COMMIT_MESSAGE;
LocalTransactionState.ROLLBACK_MESSAGE;
LocalTransactionState.UNKNOW将本地事务执行状态返回给broker,
如果是COMMIT_MESSAGE,则将不可见消息变为可消费;
如果是ROLLBACK_MESSAGE,broker会回收step1中的不可见消息,同时producer本地请手动回退(自己设计的回退方案,而非数据库的rollback,因为在虚线1中你已经将pruducer本地事务进行了commit);
如果是UNKNOW或者producer与broker网络异常,broker会定时主动回调producer中的回调函数checkLocalTransaction()去判断producer本地事务是否正常(一般是查询数据库中数据是否已经持久化),broker定时主动查看producer本地事务的逻辑应该是写在rocket server的代码中,目前尚未找到源码,但是查阅各种资料和博客,都有提到。
4、消费者消费消息,即执行另外的事物
5、
如果有消息消费失败了,则将失败的消息回传给broker,即重新写入commitLog文件,消费者将重新消费;如果消息回传的时候,consumer和broker之间网络断开,则consumer会调用submitConsumeRequestLater()方法,在consumer端进行重新消费,如果仍然消费失败,会不断重试直到达到默认的16次,你可以使用msg.getReconsumeTimes()方法来获取当前重试次数,如果重试次数足够多之后仍然无法消费成功,必须通过工单、日志等方式进行人工干预以让producer事务进行回退处理。