基于本地消息表的分布式事务

分布式事务概念

在微服务架构下,一个大的操作往往由不同的小操作组成,并且这些小操作分布在不同的服务器上,对应不同的数据库,分布式事务需要保证这些小操作要么全部成功要么全部失败,即保证数据一致性。

例如一个支付业务:

在某些业务场景下,用户发起支付申请,只要申请成功,就可以做其他事情。

正常流程

  1. 系统接受到申请后,支付申请服务经过一些业务校验,先落支付申请库
  2. 再将消息发送至MQ
  3. 支付交易服务监听到MQ消息进行进一步的处理落库。

但此时也有一些新的问题出现:

  • 若支付申请服务完成逻辑后,在投递消息到MQ中间件的过程中由于网络抖动等原因,没有投递到MQ中导致消息丢失了怎么办?
  • MQ接收到消息后,由于内部原因导致消息丢失了怎么办?
  • 支付交易服务在监听消息的过程中,由于网络原因没有接收到消息或消费过程中遇到异常,此时也会导致消息丢失,怎么办?
  • 由于MQ组件问题,导致支付交易服务重复消费怎么办?

针对前三种问题,都是消息丢失导致的,可以采用本地消息表+定时任务来解决。

针对第四种问题,是因为重复消费导致的,就需要支付交易服务做好幂等防重

增加本地消息表+定时任务

此时数据流程如下:

正向流程:

  1. 系统接受到申请后,在同一本地事务写入本地消息表和业务表,本地消息表状态为处理中,再发送消息到MQ
  2. 支付交易服务监听到消息后,进行一些逻辑之后,将结果发送至MQ
  3. 支付申请监听到处理结果,更新本地消息表的状态,处理结束

补偿措施:

  1. 假如消息丢失,还有定时任务定时扫描本地消息表中状态为处理中的数据,进行下发,后续处理和正向流程的2、3一致

特点

  1. 最大努力通知
  2. 最终一致性

注意

  1. 真实业务处理的状态可能会有多种,因此需要明确哪种状态需要定时任务补偿
  2. 假如某条单据一直无法处理结束,定时任务也不能无限制下发,所以本地消息表需要增加轮次的概念,重试多少次后告警,人工介入处理
  3. 因为MQ和定时任务的存在,难免会出现重复请求,因此下游要做好幂等防重,否则会出大问题
原文地址:https://www.cnblogs.com/jiezai/p/15480781.html