基于可靠消息服务的分布式事务演进

最终一致性
【基于可靠消息服务的分布式事务演进】最终一致性指的是两个系统的状态保持一致,要么都成功,要么都失败 。当然有个时间限制,理论上越快越好,但实际上在各种异常的情况下,可能会有一定延迟达到最终一致状态,但最后两个系统的状态是一样的 。
对于这个时间限制,个人理解:
1. 首先与系统有关,系统对实时性要求不高 。
2. 时间保证在可接收范围,否则用户体验不好
基于可靠消息服务的分布式事务演进

基于可靠消息服务的分布式事务演进

文章插图
流程:
1、系统A处理任务
2、处理完后发送消息给消息中间件
3、消息持久化
4、消息投递给系统B
5、系统处理任务B
基于可靠消息服务的分布式事务演进

文章插图
问题:
1、如果系统A处理任务完成,消息发送失败
2、由于网络原因,消息投递失败
3、处理系统B处理任务失败
解决方案: 针对问题一,需要上游系统信息一定成功发送
在系统A处理任务完成后,在本地记录待发送信息 。一个定时任务不断检查,是否发送成功,如果发送成功,将记录状态修改 。
基于可靠消息服务的分布式事务演进

文章插图
针对问题二,需要一定会保证消息被下游系统成功消费掉
如果消息在投递过程中丢失,或消息的确认应答在返回途中丢失,那么消息中间件在等待确认应答超时之后就会重新投递,直到下游消费者返回消费成功响应为止 。
基于可靠消息服务的分布式事务演进

文章插图
针对问题三,需要任务B重试机制
当任务处理失败后,则返回给消息中间件失败,在解决第二个问题的基础上 。消息会重复发送,也就是任务B重试
基于可靠消息服务的分布式事务演进

文章插图

基于可靠消息服务的分布式事务演进

文章插图
问题
1、由于网络问题,消息投递超时,消息中介件重试,又发送的一条消息 。此时系统接受到了第一条消息,处理任务B 。又接受到第二条消息,处理任务B 。任务B执行了2次
2、任务B处理一直失败,消息一直重试发送?
针对问题一,需要对消息做幂等
任务B处理消息前,先查询该消息是否被消费,如果没消费,处理任务B成功,记录消息 。如果消息已经被消费,直接返回应答成功
基于可靠消息服务的分布式事务演进

文章插图
针对问题二,对任务进行重试限制,并记录消息
任务B执行一直失败,说明程序有问题,没必要一直重试 。记录消息,(等待人工处理,或定时任务再重新执行)
基于可靠消息服务的分布式事务演进

文章插图
最终系统
基于可靠消息服务的分布式事务演进

文章插图
总结:最终一致性,主要是用“记录”和“补偿”的方式 。
在做所有的不确定的事情之前,先把事情记录下来,然后去做不确定的事情,结果可能是:成功、失败或是不确定,“不确定”(例如超时等)可以等价为失败 。成功就可以把记录的东西清理掉了,对于失败和不确定,可以依靠定时任务等方式把所有失败的事情重新搞一遍,直到成功为止 。