基于消息最终一致性解决方案

Posted xieyanke

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于消息最终一致性解决方案相关的知识,希望对你有一定的参考价值。

问题思考

订单系统和积分系统、财务记账系统在不同的系统中,如果订单操作成功,积分系统或财务系统没有对应的记录,就会造成数据不一致的情况,在这种背景下就需要有一套方案解决不一致的情况.
方案图如下(龙果学院方案图):
     技术图片
 
 
在这个案例中只列举两个系统之间的分布式事务,可以简单的理解为订单系统和记账系统

示例图解释

  1.   蓝色虚线块:事务主动发起方,整个流程的起源,可以理解为在订单系统用户支付环节
  2.   紫色虚线块:消息服务子系统,将消息存入数据库,保证消息可靠性
  3.   绿色虚线块:事务被调用方,可以理解为记账系统对这次支付操作进行记账  
  4.   消息状态确认子系统:确认消息被成功消费,如果没有成功消费则作为补偿需要重新发送
  5.   消息恢复子系统:消息服务子系统的消息在多次发送之后仍没有被 “被动放应用系统” 确认消费则需要挂起,消息恢复子系统的任务就是让“消息服务子系统”的消息重新激活并发送,确保 “被动方应用系统”重新上线后可以消费掉此消息

调用流程与容错处理

正常流程: 1预发消息 2dubbo返回 3确认并发送 4发送消息 5监听接收消息 6ACK确认已收到 7确认该条事务已处理成功;
异常流程:
  1.   若是1或2失败,则整个事务失败
  2.   若是3失败,则“消息状态子系统”扫描“消息服务子系统”中的存储在表中的预处理数据,并反向查询“主动应用系统”,如果“主动应用系统”查询到的订单状态是已处理完成,则调用“消息服务子系统”的储存的消息状态修改为已发送待消费接口并调用“消息服务子系统”的发送消息接口。
  3.   若是4失败,意味着“被动方应用系统”无法消费消息,那么必然不会执行7,此时就需要“消息恢复子系统”,定期检查“消息服务子系统”中的未确认已过期消息,并由“消息恢复子系统”重新发送出去,若消息已发出并走正常流程,则会被7确认已处理并消费
  4.   若是5失败,则和异常流程c一样,由“消息恢复子系统”处理
  5.   若是6失败,而7已经成功确认,则此条消息就会被重复消费,那么就体现出幂等的重要性,当“被动方应用系统”消费消息时需要做幂等处理,避免重复操作
  6.   若是7失败,此时的影响就是“被动方应用系统”成功消费并处理成功,但是未通知到“消息服务子系统”,那么当“消息恢复子系统”子系统重新发送消息时,需要做幂等处理,并重新走7流程;

拓展

  •  图中紫色部分 消息服务子系统、消息确认子系统、消息恢复子系统设置成3个系统的原因是为了解耦
  •  消息服务子系统具备消息存储和消息发送功能, 主要体现在能力的提供,可作为公用服务
  •  消息恢复子系统和消息确认子系统则与业务密切相关, 需要根据消息查询具体业务是否处理成功,所以独立出来
  •  现实中业务量不大的情况下, 消息确认服务以模块的方式集成到调用业务系统中, 消息恢复子系统集成到消息子系统中, 从而只需要部署一个服务即可
  •  消息服务子系统中可以使用redis分布式锁提升性能(重复操作时)

总结

  • 分布式事务中幂等判断非常重要
  • 网络是不可靠的,任何流程都有可能失败,需要多种失败补偿策略
  • 与基于DAO层分布式事务相比较; 优点是可控性强和可视化,代码解耦,削峰填谷; 缺点是只能用于通知型事务,时效性 不足, 编码量较多, 有代码侵入.
      

以上是关于基于消息最终一致性解决方案的主要内容,如果未能解决你的问题,请参考以下文章

分布式事务之解决方案(可靠消息最终一致性)

RocketMQ可靠消息最终一致性解决方案

分布式事务常见解决方案与最终一致性

[转帖]如何选择分布式事务形态(FescarTCCSAGA补偿基于消息的最终一致

如何选择分布式事务形态(TCC,SAGA,2PC,基于消息最终一致性等等)

RocketMQ系列事务消息(数据库|最终一致性)