【郑州校区】学成在线-第19天-讲义-分布式事务 四
2.4.3 消息队列实现最终一致
本方案是将分布式事务拆分成多个本地事务来完成,并且由消息队列异步协调完成,如下图:
下边以下单减少库存为例来说明:
1、订单服务和库存服务完成检查和预留资源。
2、订单服务在本地事务中完成添加订单表记录和添加“减少库存任务消息”。
3、由定时任务根据消息表的记录发送给MQ通知库存服务执行减库存操作。
4、库存服务执行减少库存,并且记录执行消息状态(为避免重复执行消息,在执行减库存之前查询是否执行过此消息)。
5、库存服务向MQ发送完成减少库存的消息。
6、订单服务接收到完成库存减少的消息后删除原来添加的“减少库存任务消息”。
实现最终事务一致要求:预留资源成功理论上要求正式执行成功,如果执行失败会进行重试,要求业务执行方法实现幂等。
优点 :
由MQ按异步的方式协调完成事务,性能较高。
不用实现try/confifirm/cancel接口,开发成本比TCC低。
缺点:
此方式基于关系数据库本地事务来实现,会出现频繁读写数据库记录,浪费数据库资源,另外对于高并发操作不是最佳方案。
2.5 自动添加选课方案
2.5.1 搭建环境
根据自动选课需求,为了更好的分析解决方案,这里搭建订单工程及数据库。
2.5.2.1 创建订单工程
导入资料下的xc-service-manage-order工程。
2.5.2.2 创建订单数据库
1、创建订单数据库xc_order(MySQL)
导入xc_order.sql
1)xc_orders:订单主表
记录订单的主要信息
3)xc_orders_pay:订单支付表
记录订单的支付状态
在任务表中包括了交换机的名称、路由key等信息为了是将任务的处理做成一个通用的功能。
考虑分布式系统并发读取任务处理任务的情况发生项目使用乐观锁的方式解决并发问题。
已完成任务表:
2.5.2 解决方案
本项目综合考虑选择基于消息的分布式事务解决方案,解决方案如下图:
1、支付成功后,订单服务向本地数据库更新订单状态并向消息表写入“添加选课消息”,通过本地数据库保证订单
状态和添加选课消息的事务。。
2、定时任务扫描消息表,取出“添加选课任务“并发向MQ。
3、学习服务接收到添加选课的消息,先查询本地数据库的历史消息表是否存在消息,存在则说明已经添加选课,
否则向本地数据库添加选课,并向历史消息表添加选课消息。这里选课表和历史消息表在同一个数据库,通过本地
事务保证。
4、学习服务接收到添加选课的消息,通过查询消息表判断如果已经添加选课也向MQ发送“完成添加选课任务的消
息”,否则则添加选课,完成后向MQ发送“完成添加选课任务的消息”,
5、订单服务接收到完成选课的消息后删除订单数据库中消息表的“添加选课消息”,为保证后期对账将消息表的消
息先添加到历史消息表再删除消息,表示此消息已经完成。
|