消息最终一致性处理分布式事务的理解

前言

消息最终一致性是用于处理分布式事务解决方案之一,其中主要保证的目的是为了消息的可靠性,最终一致性,而可靠消息并不可靠,由于其它未知原因(如网络、宕机等),依然可能会造成消息的中断,发不出去的情况,就需要人工介入处理或者有一定的处理机制,所以在一定角度上来说,可靠消息在某一程度上,只是最大保障了消息的最终一致性,以为称“消息最终一致性”会更为合理。

以下为分析消息最终一致性,其中按的思路为ACID,即事务的主要特性。

传统事务处理

举例一个场景,以CURD事务举例,一个事务中有添加、删除、修改三个操作,这里我们且称添加为A,删除为B,修改为C,设置A,B,C为同步操作,则一个事务表示为(序号表示执行顺序):

在这一事务中,可以用传统的处理方案处理,保证事务的一致性。

分布式事务处理

由于业务的发展,业务独立在一定程度上更好有效的解决了耦合,达到可扩展,组件化,高性能等,在服务化之后,我们继续使用上面的A、B、C来说明,假设已经分为A服务,B服务,C服务,实际的业务场景则为:

为了保证ACID,在A完成之后,一定要操作B服务,在B完成之后,一定要操作C,但实际中,网络、应用稳定性、异步调用等的不确定性,容易造成事务不统一,如A完成,在调用B时,由于网络或者其它原因,B并没有完成业务操作,同样,C 也没有完成,如下图:

以上的情况,这个事务并不统一,服务是独立的,要实现A回滚的操作,需要做更多的额外工作来处理。所以,为了确定B一定执行,在已完成的事务(如A)需要重复去调用或者有一种验证机制去确定B一定执行。

以上只是一种情况,可能出现多种情况。总之,打破了事务的ACID原则,而我们要做的就是尽最大努力确保这个ACID原则,即事务性。消息最终一致性的方案,为保持这个原则,做了一个保障方案。

消息最终一致性方案

注:可靠消息是一种基于消息中间件的包装,确保消息一致性的服务或者组件。

此方案中引入了可靠消息做为媒介,如图(序号表示执行顺序):

在A完成之后,会一定去调用B服务,B服务一定会去调用C服务,确保一定会完成ACID的操作。

如果说事务失败,即在A失败,这部分可以在A服务内自己控制事务,包括异常处理等,就不会去调用B,此时,整个事务就不会进行。

回到之前的事务讨论

前面提过,添加为A,删除为B,修改为C,其中A,B成功,C操作失败,要不要做A、B回滚的处理?这个之前很多同事都有提问到。事务具有ACID特性,即整个事务来说,对消费方来说是透明的,要么成功,要么失败,A、B属于事务中的一部分,不会有回滚的操作,因为它会确保C一定去执行。

如果需要添加回滚,在程序上处理可实现,考虑到开发成本上,不太建议。如有更好的办法,也希望学习。

可靠消息对业务有一定的入侵性,并不能完全解耦,如在做幂等处理时,需要跟具体业务结合判断。

总结

针对以上可靠消息的特性及使用场景,在划分服务颗粒度上需按实际业务场景划分,以最简单的成本,解决最实际的问题。