分布式事务概念
在微服务架构下,一个大的操作往往由不同的小操作组成,并且这些小操作分布在不同的服务器上,对应不同的数据库,分布式事务需要保证这些小操作要么全部成功要么全部失败,即保证数据一致性。
例如一个支付业务:
在某些业务场景下,用户发起支付申请,只要申请成功,就可以做其他事情。
正常流程:
- 系统接受到申请后,支付申请服务经过一些业务校验,先落支付申请库
- 再将消息发送至MQ
- 支付交易服务监听到MQ消息进行进一步的处理落库。
但此时也有一些新的问题出现:
- 若支付申请服务完成逻辑后,在投递消息到MQ中间件的过程中由于网络抖动等原因,没有投递到MQ中导致消息丢失了怎么办?
- MQ接收到消息后,由于内部原因导致消息丢失了怎么办?
- 支付交易服务在监听消息的过程中,由于网络原因没有接收到消息或消费过程中遇到异常,此时也会导致消息丢失,怎么办?
- 由于MQ组件问题,导致支付交易服务重复消费怎么办?
针对前三种问题,都是消息丢失导致的,可以采用本地消息表+定时任务来解决。
针对第四种问题,是因为重复消费导致的,就需要支付交易服务做好幂等防重。
增加本地消息表+定时任务
此时数据流程如下:
正向流程:
- 系统接受到申请后,在同一本地事务写入本地消息表和业务表,本地消息表状态为处理中,再发送消息到MQ
- 支付交易服务监听到消息后,进行一些逻辑之后,将结果发送至MQ
- 支付申请监听到处理结果,更新本地消息表的状态,处理结束
补偿措施:
- 假如消息丢失,还有定时任务定时扫描本地消息表中状态为处理中的数据,进行下发,后续处理和正向流程的2、3一致
特点
- 最大努力通知
- 最终一致性
注意
- 真实业务处理的状态可能会有多种,因此需要明确哪种状态需要定时任务补偿
- 假如某条单据一直无法处理结束,定时任务也不能无限制下发,所以本地消息表需要增加轮次的概念,重试多少次后告警,人工介入处理
- 因为MQ和定时任务的存在,难免会出现重复请求,因此下游要做好幂等防重,否则会出大问题