当前位置:   article > 正文

【面试题】分布式事物_面试题 分布式事务

面试题 分布式事务
什么是分布式事务

分布式事务用于在分布式系统中保证不同节点之间的数据一致性。

分布式事务实现一:XA协议

XA协议包含两阶段提交(2PC)和三阶段提交(3PC)两种实现。
在XA协议中包含着两个角色:事务协调者和事务参与者。

正向流程
第一阶段:

在这里插入图片描述
事务协调者的节点会首先向所有的参与者节点发送Prepare请求。
事物参与者在接到Prepare请求之后,每一个参与者节点会各自执行与事务有关的数据更新,写入Undo Log和Redo Log。如果参与者执行成功,暂时不提交事务,而是向事务协调节点返回“完成”消息。

当事务协调者接到了所有参与者的返回消息,整个分布式事务将会进入第二阶段。

第二阶段:

在这里插入图片描述
如果事务协调节点在之前所收到都是正向返回,那么它将会向所有事务参与者发出Commit请求。
事务参与者接到Commit请求之后,事务参与者节点会各自进行本地的事务提交,并释放锁资源。当本地事务完成提交后,将会向事务协调者返回“完成”消息。

当事务协调者接收到所有事务参与者的“完成”反馈,整个分布式事务完成。

反向流程
第一阶段

在这里插入图片描述

第二阶段

在这里插入图片描述
如果某个事务参与者反馈失败消息,说明该节点的本地事务执行不成功,必须回滚。

于是在第二阶段,事务协调节点向所有的事务参与者发送Abort请求。接收到Abort请求之后,各个事务参与者节点需要在本地进行事务的回滚操作,回滚操作依照Undo Log来进行。

XA两阶段提交的不足

1.性能问题
在事务执行过程中,各个节点占用着数据库资源,只有当所有节点准备完毕,事务协调者才会通知提交,参与者提交后释放资源。这样的过程有着非常明显的性能问题。
2.协调者单点故障问题
事务协调者是整个XA模型的核心,一旦事务协调者节点挂掉,参与者收不到提交或是回滚通知,参与者会一直处于中间状态无法完成事务。
3.丢失消息导致不一致性
在XA协议的第二个阶段,如果发生局部网络问题,一部分事务参与者收到了提交消息,另一部分事务参与者没收到提交消息,那么就导致了节点之间数据的不一致。

如果避免XA两阶段提交的种种问题呢?有许多其他的分布式事务方案可供选择:

1.XA三阶段提交
XA三阶段提交在两阶段提交的基础上增加了CanCommit阶段,并且引入了超时机制。一旦事物参与者迟迟没有接到协调者的commit请求,会自动进行本地commit。这样有效解决了协调者单点故障的问题。但是性能问题和不一致的问题仍然没有根本解决。

2.MQ事务
利用消息中间件来异步完成事务的后一半更新,实现系统的最终一致性。这个方式避免了像XA协议那样的性能问题。

3.TCC事务
TCC事务是Try、Commit、Cancel三种指令的缩写,其逻辑模式类似于XA两阶段提交,但是实现方式是在代码层面来人为实现。

分布式事务实现二:rabbitMQ事务

在这里插入图片描述

可靠生产

在这里插入图片描述
在这里插入图片描述

可靠消费
  1. 控制重试次数+死信队列
  2. try+catch+手动ack+死信队列处理+人工干预
    在这里插入图片描述
总结

优点:

耦合度低

缺点:

基于消息中间件,只适合异步
消息会延迟,需要业务上可以容忍

建议

将非核心业务做成异步

分布式事务实现三:TCC
TCC 实现阶段一:Try

在这里插入图片描述

TCC 实现阶段二:Confirm

在这里插入图片描述

TCC 实现阶段三:Cancel

在这里插入图片描述

分布式事务实现二:rocketMQ事务
普通消息的处理流程

在这里插入图片描述

  1. 消息生成者发送消息
  2. MQ收到消息,将消息进行持久化,在存储中新增一条记录
  3. 返回ACK给消费者
  4. MQ push 消息给对应的消费者,然后等待消费者返回ACK
  5. 如果消息消费者在指定时间内成功返回ack,那么MQ认为消息消费成功,在存储中删除消息,即执行第6步;如果MQ在指定时间内没有收到ACK,则认为消息消费失败,会尝试重新push消息,重复执行4、5、6步骤
  6. MQ删除消息
事务消息处理的流程

在这里插入图片描述

  1. 事务消息与普通消息的区别就在于消息生产环节,生产者首先预发送一条消息到MQ(这也被称为发送half消息)
  2. MQ接受到消息后,先进行持久化,则存储中会新增一条状态为待发送的消息
  3. 然后返回ACK给消息生产者,此时MQ不会触发消息推送事件
  4. 生产者预发送消息成功后,执行本地事务
  5. 执行本地事务,执行完成后,发送执行结果给MQ
  6. MQ会根据结果删除或者更新消息状态为可发送
  7. 如果消息状态更新为可发送,则MQ会push消息给消费者,后面消息的消费和普通消息是一样的
支持事物消息的MQ

对于RocketMQ而言,它的解决方案非常的简单,就是其内部实现会有一个定时任务,去轮训状态为待发送的消息,然后给producer发送check请求,而producer必须实现一个check监听器,监听器的内容通常就是去检查与之对应的本地事务是否成功(一般就是查询DB),如果成功了,则MQ会将消息设置为可发送,否则就删除消息。

常见的问题
问:如果预发送消息失败,是不是业务就不执行了?

是的,对于基于消息最终一致性的方案,一般都会强依赖这步,如果这个步骤无法得到保证,那么最终也 就不可能做到最终一致性了。

问:为什么要增加一个消息预发送机制,增加两次发布出去消息的重试机制,为什么不在业务成功之后,发送失败的话使用一次重试机制?

如果业务执行成功,再去发消息,此时如果还没来得及发消息,业务系统就已经宕机了,系统重启后,根本没有记录之前是否发送过消息,这样就会导致业务执行成功,消息最终没发出去的情况。

问:如果consumer消费失败,是否需要producer做回滚呢?

这里的事务消息,producer不会因为consumer消费失败而做回滚,采用事务消息的应用,其所追求的是高可用和最终一致性,消息消费失败的话,MQ自己会负责重推消息,直到消费成功。因此,事务消息是针对生产端而言的,而消费端,消费端的一致性是通过MQ的重试机制来完成的。

问:如果consumer端因为业务异常而导致回滚,那么岂不是两边最终无法保证一致性?

基于消息的最终一致性方案必须保证消费端在业务上的操作没障碍,它只允许系统异常的失败,不允许业务上的失败,比如在你业务上抛出个NPE之类的问题,导致你消费端执行事务失败,那就很难做到一致了。

来源:https://blog.csdn.net/bjweimengshu/article/details/79607522
来源:https://www.jianshu.com/p/04bad986a4a2
TCC:https://www.cnblogs.com/jajian/p/10014145.html

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/290431
推荐阅读
相关标签
  

闽ICP备14008679号