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

最终一致性

最终一致性指的是两个系统的状态保持一致,要么都成功,要么都失败。当然有个时间限制,理论上越快越好,但实际上在各种异常的情况下,可能会有一定延迟达到最终一致状态,但最后两个系统的状态是一样的。

对于这个时间限制,个人理解:
1. 首先与系统有关,系统对实时性要求不高。
2. 时间保证在可接收范围,否则用户体验不好

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

image_1c7svg4218g9juvl9e12hadv99.png-25.9kB

流程:

1、系统A处理任务
2、处理完后发送消息给消息中间件
3、消息持久化
4、消息投递给系统B
5、系统处理任务B

问题:

1、如果系统A处理任务完成,消息发送失败
2、由于网络原因,消息投递失败
3、处理系统B处理任务失败

解决方案:

针对问题一,需要上游系统信息一定成功发送

在系统A处理任务完成后,在本地记录待发送信息。一个定时任务不断检查,是否发送成功,如果发送成功,将记录状态修改。

image_1c7t0rtvo1hpj1mk7j9t6il18u5m.png-43.3kB

针对问题二,需要一定会保证消息被下游系统成功消费掉

如果消息在投递过程中丢失,或消息的确认应答在返回途中丢失,那么消息中间件在等待确认应答超时之后就会重新投递,直到下游消费者返回消费成功响应为止。

image_1c7t1om0rk4c1s0415ieasb9s23d.png-51.3kB

针对问题三,需要任务B重试机制

当任务处理失败后,则返回给消息中间件失败,在解决第二个问题的基础上。消息会重复发送,也就是任务B重试

image_1c7t1umrs18qp1v071a301nkm1lm63q.png-70.6kB

问题

1、由于网络问题,消息投递超时,消息中介件重试,又发送的一条消息。此时系统接受到了第一条消息,处理任务B。又接受到第二条消息,处理任务B。任务B执行了2次

2、任务B处理一直失败,消息一直重试发送?

针对问题一,需要对消息做幂等

任务B处理消息前,先查询该消息是否被消费,如果没消费,处理任务B成功,记录消息。如果消息已经被消费,直接返回应答成功

image_1c7t2kf0s1kk5kphnno1uv01mmd47.png-58.5kB

针对问题二,对任务进行重试限制,并记录消息

任务B执行一直失败,说明程序有问题,没必要一直重试。记录消息,(等待人工处理,或定时任务再重新执行)

image_1c7t375071ifo2gitqckuq2nc4k.png-107.3kB

最终系统

image_1c7t4q1qgs6ku06170bthdg246b.png-59.4kB

总结:最终一致性,主要是用“记录”和“补偿”的方式。

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

猜你喜欢

转载自blog.csdn.net/u012092620/article/details/80222007