分布式事务选型及对比


什么是分布式事务?
当A服务调用B服务成功以后,A服务报错导致事务回滚,B服务事务提交,导致数据不一致性的问题。

分布式事务产生的条件
说到分布式事务,我们先来看看分布式事务的产生条件
这里我们举一个栗子:
在这里插入图片描述

  1. 当用户进行下单以后,会去调用派单服务进行派单,即向派单服务数据库中插入一条派单业务。
  2. 派单成功之后,订单服务在执行后面的业务代码中,报错了
  3. 此时订单服务事务回滚,而派单服务的事务已经提交了,导致了数据的不一致。
此时,小伙伴可能有疑问:派单服务报错呢?会不会也产生分布式事务问题?
实际上如果派单服务报错,会将执行结果返回给订单服务,订单服务执行相应的处理即可,并不会发生分布式事务。

分布式事务的解决方案有哪些?

  • 基于Lcn解决分布式事务
  • 基于阿里巴巴seata解决分布式事务
  • 基于RabbitMq解决分布式事务
  • 基于RocketMq解决分布式事务

1、基于Lcn解决分布式事务

LCN实现原理

  1. 发起方与参与方都与我们的LCN管理器一直保持长连接;
  2. 发起方在调用接口之前,先向LCN管理器申请一个全局的事务分组id;
  3. 发起方调用接口的时候在请求头中传递事务分组id;
  4. 参与方获取到请求头中有事务分组的id的,则当前业务逻辑执行完实现假关闭,不会提交或者回滚当前的事务。
  5. 发起方调用完接口后,如果出现异常的情况下,在通知给事务协调者回滚事务,这时候事务协调则告诉给参与方回滚当前的事务。

2、阿里巴巴seata框架

在这里插入图片描述
和上面一样,订单服务为发起方、派单服务为参与方

  1. 发起方(TM)和参与方(RM)项目启动后会和协调者(TC)保持长连接
  2. 发起方(TM)在调用参与方(TC)之前,会向协调者(TC)申请一个全局事务id(Xid),并保存到ThreadLocal中
  3. 发起方(TM)和参与方(RM)都会被seata代理数据源,利用aop在执行insert、update、delete语句之前和之后生成前置镜像和后置镜像,并写入到undo_log表中
  4. 发起方(TM)重写feign客户端请求,将全局事务id保存到请求头中传递给参与方(RM),参与方(RM)获取全局事务id,并在协调者(TC)中注册该分支
  5. 发起方(TM)调用参与方(RM)接口成功以后,执行本地业务代码也成功后,会将发起方(TM)本地事务结果commit通知给协调者(TC),协调者(TC)再将事务结果通知给给各事务分支(即参与方(RM))。
  6. 发起方(TM)调用参与方(RM)接口成功以后,执行本地业务代码失败,此时会产生分布式事务问题,发起方(TM)本地事务结果rollback通知给协调者(TC),协调者(TC)再将事务结果通知给给各事务分支(即参与方(RM))。
  7. 参与方(RM)接收到事务结果通知,如果是commit的情况下,代表事务执行成功,删除掉undo_log中对应的分支id的记录即可
  8. 参与方(RM)接收到事务结果通知,如果是rollback的情况下,代表事务执行失败,根据undo_log日志,逆向生成sql语句,比如先前是插入,现在就是删除。去删除掉相应的记录,完成以后,再删掉undo_log日志对应的记录。
    优点
  9. seata的性能比lcn要好
  10. seata不会造成死锁的情况

缺点

  1. seata没有管理化界面
  2. seata会造成数据的脏读,不能保证数据的强一致性,只能保证最终一致性

seata和lcn比较,有什么不一致?

  • seata和lcn大致的实现思路是一致的,但是回滚的机制不一样。
  • lcn是采取代理数据源的模式,再根据发起方执行本地事务的结果进行回滚或者提交
  • seata采取的是根据undo_log日志表,进行逆向生成sql语句,来解决回滚
  • lcn能够保证强一致性,但可能发生死锁的现象
  • seata能保证最终一致性,但可能造成脏读

3、基于RabbitMQ解决分布式事务

在这里插入图片描述
实现流程

  1. 确保生产者投递消息成功,使用消息确认机制confirm,如果消息投递失败,人工进行补偿
  2. 确保消费者消费成功,采用手动ack的形式。如果消费失败,mq自动帮我们补偿,如果达到补偿上线,进行日志记录或者放入死信队列,后期进行人工补偿
  3. 当订单生产者投递成功以后,后续代码报错,导致事务回滚,我们需要采用补单队列,即订单生产者在投递消息的时候,不光要投递派单消息,还需要把订单消息一并带过去,补单消费者接收到消息以后,先去数据库查询数据是否存在,如果不存在的话,补单消费者进行补单
    优点
  • 基于mq的形式实现,具有重试、消息持久化机制

缺点

  • RabbitMQ实现起来比较麻烦,需要手动添加补单消费者。

4、基于RocketMQ解决分布式事务

RocketMQ也是阿里巴巴开发的框架,是再kafka的基础上进行改造升级,自带解决分布式事务的功能,主要采用事务消息来解决分布式事务
在这里插入图片描述
原理分析:

  1. 生产者向Broker投递半消息,(半消息是不能被消费者进行消费的)
  2. Broker返回消息投递成功的结果
  3. 生产者执行本地事务,再将本地事务的结果返回给Broker
  4. 本地事务提交有两种情况,如果返回的成功是,COMMIT,则代表事务成功执行,然后标记该半消息可以为消费者消费。如果事务返回的是ROLLBACK,则代表事务执行失败,进行了回滚,Broker将会把该半消息移除
  5. broker根据事务结果决定该半消息是否让消费者消费
  6. 如果本地事务执行时间太久,或者是因为网络原因导致本地事务结果没有告诉Broker,Broker将每隔一分钟主动查询一次本地事务执行的结果。总共重试15次。以此判断半消息是否可以被消费

优点

  • RocketMQ具有重试机制、持久化机制、分区机制、天生抗并发能力强。
  • RocketMQ已经帮我们解决了分布式事务

缺点

  • 可能功能上没有阿里云的付费产品ons强大吧

那解决分布式事务该选用那种框架呢?

  1. 首先看是否能扩展机器,在有成本的情况下,尽量考虑mq,毕竟已经帮我们做好了重试,消息持久化等功能
  2. RabbitMQ和RockteMQ选型,尽量采用RocketMQ,RabbitMQ不是用java语言编写,扩展能力比较差,而且抗并发能力与RocktMQ相差很远
  3. lcn和seata之间选型,如果数据需要保证强一致性,就选择lcn。如果不需要,就选择seata。而且,lcn现在已经停止更新。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

redstone618

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值