涉及到分布式、微服务,面试一定会问分布式事务的处理方案,强一致性这种就不说了,很好奇现在是否还有企业在分布式系统中使用强一致性。

最终一致性的实现,例如2PC、TCC本文就不说了,性能上,实现成本上都不理想。

我从工作中以及跟朋友交流接触到的消息来看,采用MQ较多。这就衍生出一个被问到很多次的问题:给MQ发消息失败了怎么办,例如MQ服务器断电了。

基于MQ的分布式事务现在有两种。相关角色如下,生产者(P),消息队列(MQ),消费者(C),消息(MSG)

一、RocketMQ的事务消息

流程如下:

P2MQ:1.发MSG至MQ暂存,此MSG为事务消息。

11.成功。P执行本地事务。

111.本地事务成功,通知MQ确认MSG可以发送,事务消息变为普通消息。

112.本地事务失败,通知MQ删除MSG,或直接放弃,此MSG为废消息。

12.失败。P重发直至成功,或直接失败。

13.未知。MQ断电了,网络出现问题了,导致P接收不到MQ的响应,P可以重发直至成功或直接失败。直接失败也有两种情况。

131.MQ未接收到MSG,P、MQ全失败,事务没问题。

132.MQ已接收到MSG,此MSG为废消息。

2.接111,MQ接收P的确认消息。

21.成功。MQ发送MSG至C。

22.失败/未知。出现112、12、132情况,MQ一直未接收到P的确认消息,此MSG为废消息。

1、2保证了P的事务与P2MQ的事务一致性。保证不会出现P事务失败了,MQ却把MSG传给C的情况。

而RocketMQ会定期扫描没有变成普通消息的事务消息,即前文的废消息,调用P提供的检查接口,来处理这批事务消息,是清理还是继续发送。

MQ2C:3.接21,MQ通知S消费。

31.成功。后续工作交给S。

32.失败/未知。重试直至成功,S接口保证幂等。这里的成功是指S接收MSG成功,处理结果MQ不关心。

4.接31,处理本地事务。

41.成功。至此分布式事务完结。

42.失败。

421.重复消费MSG直至成功。

422.在业务上已经无成功可能,例如账户被冻结,无法接收转账。触发业务失败处理流程,通知P撤销本次业务。

这约等于MQ版的二阶段提交,但是主流的MQ,例如Kafka都不支持。

二、本地消息任务表

1、P端执行本地事务时,在消息任务表新增日志。此处可保证事务一致性。

2、在执行本地事务成功后,可以通过异步方法,或者任务调度,将消息任务表的MSG,通过重试保证消息能进入MQ,并修改本地消息任务状态。

MQ,例如Kafka,有自己的持久化机制,至此P与MQ的消息传递得到了保证。

3、MQ通过消息重发机制,确保MSG发送至S。S接口保证幂等。

4、S消费MSG直至成功。如果在业务上已无成功可能,触发业务失败处理流程,通知P撤销本次业务。




emqx5如何判断一个消息有没有被接收到_强一致性