分布式事务(三)、柔性事务之 TCC、Saga、本地消息表、事务消息、最大努力通知 - 墨天轮
https://zhuanlan.zhihu.com/p/590834427
本地消息表实现
业界常见方案,因为其他框架太重
主要思想就是将分布式事务拆分为本地事务和消息事务两个部分,本地事务在本地数据库提交or回滚,而消息事务则将消息写入消息中间内,以实现消息可靠投递和顺序性
做法
- 创建一张本地消息表,用于记录要发的消息内容
- 将业务表操作和消息表创建记录置于同一事务下(不要把发消息行为放进去,不然可能会因为网络延迟,导致生产者误认为是发送失败,造成异常回滚,实际是发送成功了)
- 消费者端消费成功后,改本地消息状态
某个环节可能出现的错误
- 消息投递失败,开定时任务,扫表重投
- 消息消费失败,依靠消息的重投机制,不断重试
- 回填状态失败,那么相当于业务数据已经一致了,但消息表里的状态是错的。
- 定时任务继续重投消息,依靠幂等校验,去推进消息状态
- 查下游系统的状态,如果成功了,则直接推进消息状态即可
优缺点
优点
- 没TCC,stea,2Pc重
- 扩展性好
- 适用范围广
缺点
- 定时任务,扫表性能较开销大
- 实现复杂度相对较高
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| @Autowired TransactionTemplate transactionTemplate;
public void order(OrderDTO orderDTO){
boolean transactionSuccess = transactionTemplate.execute(new TransactionCallback<Boolean>() { @Override public Boolean doInTransaction(TransactionStatus status) { try { orderServive.createOrder(orderDTO); messageService.createMessage(orderDTO); return true; } catch (Exception e) { status.setRollbackOnly(); return false; } } });
if (transactionSuccess) { mqService.send(orderDTO); messageService.updateSuccess(orderDTO); } else { } }
|