• 分布式事务解决方案


    分布式理论参考:分布式理论_现实、太残忍的博客-CSDN博客

    一、2pc

    一共分为两阶段:

    • 第一阶段(prepare):即所有的参与者准备执行事务并锁住需要的资源。参与者ready时,向事务管理器报告已准备就绪。
    • 第二阶段(commit/rollback):当事务管理者确认所有参与者都ready后,向所有参与者发送commit命令。

    缺点:一旦事务协调者宕机或者发生网络抖动,会让参与者一直处于锁定资源的状态或者只有一部分参与者提交成功,导致数据的不一致。因此,在⾼并发性能⾄上的场景中,基于 XA 协议的分布式事务并不是最佳选择。所以它比较适⽤于执⾏时间确定的短事务,整体性能比较差。

    目前主流的数据库基本都支持XA事务,包括MySQL、Oracle、SQL Server、PostgreSQL
     

    二、3pc

    三阶段提交(3PC)是二阶段提交(2PC)的一种改进版本 ,为解决两阶段提交协议的阻塞问题。

    2PC 中只有协调者有超时机制,3PC 在协调者和参与者中都引入了超时机制,协调者出现故障后,参与者就不会一直阻塞。而且增加了 CanCommit 阶段,保证了在最后提交阶段之前各参与节点的状态是一致的。

    1、CanCommit 阶段
    协调者询问事务参与者,是否有能力完成此次事务。如果都返回 yes,则进入第二阶段;有一个返回 no 或等待响应超时,则中断事务,并向所有参与者发送 abort 请求

    2、PreCommit 阶段
    此时协调者会向所有的参与者发送 PreCommit 请求,参与者收到后开始执行事务操作,并将 Undo 和 Redo 信息记录到事务日志中。参与者执行完事务操作后(此时属于未提交事务的状态),就会向协调者反馈“Ack”表示已经准备好提交了,并等待协调者的下一步指令。

    3、DoCommit 阶段
    在阶段二中如果所有的参与者节点都可以进行 PreCommit 提交,那么协调者就会从“预提交状态”转变为“提交状态”。然后向所有的参与者节点发送 doCommit 请求,参与者节点在收到提交请求后就会各自执行事务提交操作,并向协调者节点反馈 Ack 消息,协调者收到所有参与者的 Ack 消息后完成事务。相反,如果有一个参与者节点未完成 PreCommit 的反馈或者反馈超时,那么协调者都会向所有的参与者节点发送 abort 请求,从而中断事务。

    三、tcc

    TCC (柔性事务)其实就是采用的补偿机制,其核心思想是:针对每个操作,都要增加一个对应的确认和补偿(撤销)操作

    • Try 阶段:尝试执行,完成所有业务检查(一致性), 预留必须业务资源(准隔离性)
    • Confirm 阶段:确认执行真正执行业务,不作任何业务检查,只使用 Try 阶段预留的业务资源,Confirm 操作要求具备幂等设计,Confirm 失败后需要进行重试。
    • Cancel 阶段:取消执行,释放 Try 阶段预留的业务资源。Cancel 阶段的异常和 Confirm 阶段异常处理方案基本上一致,要求满足幂等设计。

    缺点:原本一个方法,现在却需要三个方法来支持,可以看到 TCC 对业务的侵入性很强,而且这种模式并不能很好地被复用,会导致开发量激增。还要考虑到网络波动等原因,为保证请求一定送达都会有重试机制,所以考虑到接口的幂等性。

    四、本地消息表

    执行流程:

    1. 消息生产方,需要额外建一个消息表,并记录消息发送状态。消息表和业务数据要在一个本地事务里提交,也就是说他们要在一个数据库里面(利用本地事务保证一致性)。然后消息会经过 MQ 发送到消息的消费方。如果消息发送失败,会进行重试发送。
    2. 消息消费方,需要处理这个消息,并完成自己的业务逻辑。如果是业务上面的失败,可以给生产方发送一个业务补偿消息,通知生产方进行回滚等操作。
    3. 此时如果本地事务处理成功,表明已经处理成功了。如果处理失败,那么就会重试执行。
    4. 生产方和消费方定时扫描本地消息表,把还没处理完成的消息或者失败的消息再发送一遍。

    五、事务消息

    在本地消息表(四)方案中,生产者需要额外创建消息表,还需要对本地消息表进行轮询,业务负担较重。

    RocketMQ 4.3之后的版本正式支持事务消息,该事务消息本质上是把本地消息表放到RocketMQ上,解决生产端的消息发送与本地事务执行的原子性问题。

    RocketMQ 事务消息基于两阶段提交和事务状态回查机制来实现。

    所谓的两阶段提交,即首先发送 prepare 消息,待事务提交或回滚时发送 commit、rollback 命令。 再结合定时任务,RocketMQ 使用专门的线程以特定的频率对 RocketMQ 服务器上的 prepare 信息进行处理,向发送端查询事务消息的状态来决定是否提交或回滚消息 。

    需要定义好"事务回查"接口。

    六、最大努力通知

    发起通知方尽最大的努力将业务处理结果通知为接收通知方,但是可能消息接收不到,此时需要接收通知方主动调用发起通知方的接口查询业务处理结果,通知的可靠性关键在接收通知方。

    解决方案上,最大努力通知需要:

    • 提供查询接口,让接受通知放能够通过接口查询业务处理结果
    • 消息队列ACK机制,消息队列按照间隔1min、5min、10min、30min、1h、2h、5h、10h的方式,逐步拉大通知间隔 ,直到达到通知要求的时间窗口上限。之后不再通知

    适用场景:最终一致性要求较低的业务,例如:业务通知类型的业务(微信交易的结果)。

    七、saga

    其核心思想是将长事务拆分为多个本地短事务,由Saga事务协调器协调,如果正常结束那就正常完成,如果某个步骤失败,则根据相反顺序一次调用补偿操作。

  • 相关阅读:
    Vue基础-04
    互联网摸鱼日报(2022-11-12)
    论文笔记:Convolutional Image Captioning
    transformer必考知识点
    海藻酸钠-聚乳酸|PLA-alginate|海藻酸钠-PEG-聚乳酸/聚已内酯PCL
    2022-09-01 网工进阶(二十九) DHCP-概述、工作原理、报文格式、分配IP地址顺序、地址租期与续租、中继(relay)、Snooping
    springboot 项目 运行rabbitmq(推送+消费)
    SpringSecurity5 Oauth2.1与老版本OAuth2区别
    Module object(emscripten)
    Matlab自学笔记二十四:字符串的关系运算和比较
  • 原文地址:https://blog.csdn.net/sumengnan/article/details/125438230