常见分布式事务解决方案
Posted wen-pan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了常见分布式事务解决方案相关的知识,希望对你有一定的参考价值。
一、分布式事务开源框架方案
市面上有很多开源的分布式事务框架,下面列举几个!!!
- seata,seata基本实现了最常用的各个场景的分布式事务解决方案,主要分为以下四种模式
- XA模式
- 参考:Seata XA 模式
- 缺点:需要数据库支持XA协议,长事务,持久占用资源,效率较低(分支事务需要在第二阶段执行后才进行提交或回滚)
- 优点:强一致性保证,不会有分布式事务的脏读、脏写发生
- saga模式
- 参考:SEATA Saga 模式
- Saga模式是SEATA提供的长事务解决方案,在Saga模式中,业务流程中每个参与者都提交本地事务,当出现某一个参与者失败则补偿前面已经成功的参与者,一阶段正向服务和二阶段补偿服务都由业务开发实现。
- 适用场景
- 业务流程长、业务流程多
- 参与者包含其它公司或遗留系统服务,无法提供 TCC 模式要求的三个接口
- 优点:
- 一阶段提交本地事务,无锁,高性能
- 事件驱动架构,参与者可异步执行,高吞吐
- 补偿服务易于实现
- 缺点:不保证隔离性
- TCC模式
- 参考:Seata TCC 模式
- 缺点:try、confirm、cancel三个阶段都需要自己做控制,编写起来很麻烦,自己编写的过程中需要注意的点也很多,需要对TCC模式充分了解,业务侵入性很高
- 优点:灵活性非常高,TCC每个阶段都可以自己控制
- AT模式
- 参考:Seata AT 模式
- 优点:AT模式也是基于2PC思想,但是他在第一阶段执行完后,分支事务就已经提交了,而不用等到第二阶段执行后再提交分支事务,解决了XA模式的持久占用数据库资源的重大缺陷。并且业务侵入性非常低
- 缺点:会有一定的脏读和脏写问题,参考:Seata 事务隔离级别解读
- XA模式
- XA实现方案
- 该方案需要数据库支持XA协议(现在主流的数据库都支持XA协议),但是有个致命的缺点就是事务占用时间过长,资源锁定时间过长,性能较低
- 优点是强一致性保证,不会有分布式事务的脏读、脏写发生
- Hmily
- 很小众不是很常用
二、基于本地消息表方案
本地消息表方案其实就是在数据库创建一张表,用来记录需要发送给第三方的消息记录。
以用户注册送积分场景来举例,假设用户注册时首先调用【账号服务】注册一个账号,同时需要调用【积分服务】为该用户增加积分!
①、流程
- 首先用户填写完基本信息,点击注册按钮进行注册
- 【账号服务】新增一个账号,同时往数据库的消息表里写入一条增加积分的消息(这两步操作在同一个事务内,保证了原子性),此时就可以提交事务了,表示账号注册成功
- 启动一个【定时任务】定时的触发去查询消息表中还未发送的消息,按照消息的路由将消息发送给MQ指定的队列
- 【积分服务】订阅消息队列(采用MQ的ack机制保证消息一定被消费),获取队列中的消息进行执行
增加用户积分
操作
②、优缺点分析
1、优点
- 实现较为简单,仅依赖MQ和定时任务即可
- 消息一定不会丢失,安全性较好(由于消息已经持久化到DB的消息表,所以不怕消息丢失,即使将MQ换做Redis的队列也可以)
2、缺点
- 消息接收方需要自己做幂等控制
- 基于定时任务轮询,增加积分实时性不高
- 一般不能回滚,一旦写入本地消息表成功了,则调用方的事务就提交了,如果被调用方执行消息消费时发现需要回滚调用方的事务,这是无法做到的,除非人工介入
- 基于定时任务轮询频率不好控制,并且将压力放到了DB,在DB压力大的情况下这个选择不是很好
三、基于rocketmq事务消息方案
①、流程
1、生产者向broker发送half消息(half消息并不会被立即投入到目标队列,而是先防止到一个特殊的topic队列中)
2、broker回复half消息是否成功接收
3、根据broker回复的half消息状态决定是否调用本地事务方法
- 如果half消息发送失败,则不执行本地事务
- 如果half消息发送成功,则开始执行本地事务
4、本地事务方法调用完毕后,根据本地事务方法的执行结果向broker发送 提交 或 回滚 或 unknown
消息
5、如果是提交或回滚消息,则broker直接提交或回滚(提交后消费者就可以消费该消息了)
6、如果是unknown消息,则broker会定时回查本地事务的状态(默认1一分钟一次,最大回查15次,超过15次则默认丢弃该消息)
7、broker根据回查状态来决定是否提交、回滚或丢弃该消息
- 这里防止超过最大回查次数broker仍然没有得到
commit
或rollback
响应导致该消息丢失,我们可以采用【补偿措施】将超过重试阈值的消息存放到DB表里,然后由定时任务或人工处理这些超过重试阈值的消息
8、当本地消息被正常提交后,half消息被转移到目标队列,此时消费方就可以消费该消息进行处理了
②、优缺点分析
1、优点
- 可适用于转账、注册送积分等不需要事务实时性太高的场景
- 消息的可靠性由消息发送方保证,消息发送方保证一定能将消息发送给消息接收方(由rocketMq的事务消息来保证消息发送与本地事务同时成功和失败)
2、缺点
- 不能回滚,一旦消息发出,消息接收方一定要处理这个消息
- 由于消息可能重复消费,消费方需要保证幂等性
以上是关于常见分布式事务解决方案的主要内容,如果未能解决你的问题,请参考以下文章