分布式事务 - 消息队列实现分布式事务
消息队列实现分布式事务
除了 2PC 和 TCC 两种方案外,还有另一种实现分布式事务的方案,即使用消息队列实现数据最终一致性。
以下单扣减库存为案例说明:
订单服务和库存服务完成检查和预留资源,保证事务可以正常进行。
订单服务首先收到下单请求,在本地事务中完成添加订单表记录,同时往订单服务中的消息表中添加“减少库存任务消息”。本次请求结束。
订单服务由定时任务,异步读取订单服务的消息队列表,获取待发送的消息,发送给队列,为了通知库存服务执行减库存操作。
库存服务监听消息队列中扣减库存的消息,收到消息后就更新库存,并且在消息消费历史记录中记录消息,此举是为了为避免重复扣减库存,使消息被重复消费,并且在每次执行减库存之前,都需要查询是否存在对应的消息记录,已存在则说明执行过对应的消息,相当于保证了库存服务扣减库存操作的幂等性。
库存服务处理完成后,同步的向消息队列发送已完成减少库存的消息。
订单服务接收到完成库存减少的消息后,删除消息队列表中对应的库存更新任务消息。
注意:
在此方案中,每个环节出错,都有可能进行重试,所以要尽量保证消息消费的幂等性,假设订单在插入订单数据或者插入库存扣减消息时失败,则订单服务的本地事务会执行回滚;
如果扣减库存服务消息发送失败,或者库存服务未能成功接收消息,定时任务下次执行时会重新发送;
如果库存服务本地发生扣减异常,则会重新收到消息重新进行扣减库存;
如果库存服务在未完成扣减向队列发送已完成消息前,又再次收到了重复的消息扣减,则会由幂等性保证库存不会重复扣减;
如果库存服务在完成本地事务后,未能向消息队列中发送已完成,或者订单服务未能接收到消息,则再下一次由订单发送的消息扣减会触发库存服务的消息发送(此时不会再重复扣减库存)
由以上一系列的举例说明,可以看见此方案在多种方面都有异常处理机制,保证最后事务的完成,实现最终数据一致。
总结
此方案的优点:由消息中间件异步执行,协调事务,性能很高;逻辑繁琐度较低,不用考虑事务协调者的代码
缺点:虽然执行的性能很高,但是对表的读写会很频繁,其次是事务的执行时间相对较长,在高并发的场景下不适用。
版权声明: 本文为 InfoQ 作者【zarmnosaj】的原创文章。
原文链接:【http://xie.infoq.cn/article/89d1bb435d5e9590676f618fb】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论