分布式事务

大部分内容转自:https://zhuanlan.zhihu.com/p/25933039

这里是记录下另一个解决方案,采用消息表跟MQ来完成分布式事务,这个方案还是最终一致性

基本思路就是:

  1. 消息生产方,需要额外建一个消息表,并记录消息发送状态。消息表和业务数据要在一个事务里提交。实现时为了简单,可以只是增加一个字段。新增字段会跟业务强耦合,新增表处理起来不同交易数据可以通用处理。不过因为消息表跟业务需要在一个事务里,所以存储耦合在所难免。
  2. 消息消费方,需要处理这个消息,并完成自己的业务逻辑。此时如果本地事务处理成功,那发送给生产方一个confirm消息,表明已经处理成功了。如果处理失败,该消息还是需要放回MQ的。如果MQ支持重试,那就省事儿了。如果不支持,可以考虑把该消息放回队尾或另建一个队列特殊处理。当然非要处理成功才能继续,那只能block在这条消息了(估计一般人不会这么做)。Kafka lowlevel接口是支持自己设置offset的,所以可以实现block。
  3. 生产方定时扫描本地消息表,把还没处理完成的消息由发送一遍。如果有靠谱的自动对账补账逻辑,其实这一步也可以省略。在实践中,丢消息或者下游处理失败这种场景还是非常少的。这里要看业务上能不能容忍不一致到一个对账补账周期。

这里的MQ假如采用的是RabbitMQ,因为RabbitMQ可以设置没收到Confirm时,消息依然保存在队列里,所以上面第2点提到的需要将消息放回到MQ,对RabbitMQ来说,是不需要的。

 

总结上面说的思路,举个例子,一个简单的下单流程,包括生成订单,扣库存,扣优惠券积分(如有),添加日志

这四步对应的应用在四个服务器里

另下面的重试都要实现幂等

第一步:生成订单,在执行完生成订单逻辑后,向MQ发送一条消息(处理扣库存的逻辑)

假设发送后,没收到MQ的ACK,我觉得可以重试3次,3次都不成功(指没收到ACK),则生成一条消息表记录,有两个字段,订单ID,状态字段,(这里设为0)设为未发送成功,然后定时器会定时去扫描消息表,把那些没有发送成功地消息再发送一次

生成订单和给MQ发送消息和往消息表生成消息都是在同一个事务里面,消息表跟订单表在同一个事务

第二步:MQ收到消息后,开始执行扣库存的逻辑,执行后向MQ发送一条消息(处理扣优惠卷积分的逻辑)

假设发送后,没收到MQ的ACK,我觉得可以重试3次,3次都不成功(指没收到ACK),则生成一条消息表记录,有两个字段,订单ID,状态字段,(这里设为0)设为未发送成功,然后定时器会定时去扫描消息表,把那些没有发送成功地消息再发送一次

扣库存和给MQ发送消息和往消息表生成消息都是在同一个事务里面,消息表跟库存表在同一个事务

以此类推

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值