讲解分布式事务的一篇良心之作

2024-02-11 19:08

本文主要是介绍讲解分布式事务的一篇良心之作,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

分布式事务的几种实现思路

4.1 可靠消息最终一致性方案

整个流程图如下所示:

我们来解释一下这个方案的大概流程:

  1. A系统先发送一个prepared消息到mq,如果这个prepared消息发送失败那么就直接取消操作别执行了,后续操作都不再执行

  2. 如果这个消息发送成功过了,那么接着执行A系统的本地事务,如果执行失败就告诉mq回滚消息,后续操作都不再执行

  3. 如果A系统本地事务执行成功,就告诉mq发送确认消息

  4. 那如果A系统迟迟不发送确认消息呢?

    此时mq会自动定时轮询所有prepared消息,然后调用A系统事先提供的接口,通过这个接口反查A系统的上次本地事务是否执行成功

    如果成功,就发送确认消息给mq;失败则告诉mq回滚消息(后续操作都不再执行)

  5. 此时B系统会接收到确认消息,然后执行本地的事务,如果本地事务执行成功则事务正常完成

  6. 如果系统B的本地事务执行失败了咋办?

    基于mq重试咯,mq会自动不断重试直到成功,如果实在是不行,可以发送报警由人工来手工回滚和补偿

这种方案的要点就是可以基于mq来进行不断重试,最终一定会执行成功的。

因为一般执行失败的原因是网络抖动或者数据库瞬间负载太高,都是暂时性问题。

通过这种方案,99.9%的情况都是可以保证数据最终一致性的,剩下的0.1%出问题的时候,就人工修复数据呗。

适用场景:

这个方案的使用还是比较广,目前国内互联网公司大都是基于这种思路玩儿的。

4.2 最大努力通知方案

整个流程图如下所示:

这个方案的大致流程:

  1. 系统A本地事务执行完之后,发送个消息到MQ

  2. 这里会有个专门消费MQ的最大努力通知服务,这个服务会消费MQ,然后写入数据库中记录下来,或者是放入个内存队列。接着调用系统B的接口

  3. 假如系统B执行成功就万事ok了,但是如果系统B执行失败了呢?

    那么此时最大努力通知服务就定时尝试重新调用系统B,反复N次,最后还是不行就放弃。

这套方案和上面的可靠消息最终一致性方案的区别:

可靠消息最终一致性方案可以保证的是只要系统A的事务完成,通过不停(无限次)重试来保证系统B的事务总会完成

但是最大努力方案就不同,如果系统B本地事务执行失败了,那么它会重试N次后就不再重试,系统B的本地事务可能就不会完成了。

至于你想控制它究竟有“多努力”,这个需要结合自己的业务来配置。

比如对于电商系统,在下完订单后发短信通知用户下单成功的业务场景中,下单正常完成,但是到了发短信的这个环节由于短信服务暂时有点问题,导致重试了3次还是失败。

那么此时就不再尝试发送短信,因为在这个场景中我们认为3次就已经算是尽了“最大努力”了。

简单总结:就是在指定的重试次数内,如果能执行成功那么皆大欢喜,如果超过了最大重试次数就放弃,不再进行重试。

适用场景:

一般用在不太重要的业务操作中,就是那种完成的话是锦上添花,但失败的话对我也没有什么坏影响的场景。

比如上边提到的电商中的部分通知短信,就比较适合使用这种最大努力通知方案来做分布式事务的保证。

4.3  tcc强一致性方案

TCC的全称是:

  • Try(尝试)

  • Confirm(确认/提交)

  • Cancel(回滚)。

这个其实是用到了补偿的概念,分为了三个阶段:

  1. Try阶段:这个阶段说的是对各个服务的资源做检测以及对资源进行锁定或者预留;

  2. Confirm阶段:这个阶段说的是在各个服务中执行实际的操作;

  3. Cancel阶段:如果任何一个服务的业务方法执行出错,那么这里就需要进行补偿,就是执行已经执行成功的业务逻辑的回滚操作;

还是给大家举个例子:

比如跨银行转账的时候,要涉及到两个银行的分布式事务,如果用TCC方案来实现,思路是这样的;

  1. Try阶段:先把两个银行账户中的资金给它冻结住就不让操作了

  2. Confirm阶段:执行实际的转账操作,A银行账户的资金扣减,B银行账户的资金增加

  3. Cancel阶段:如果任何一个银行的操作执行失败,那么就需要回滚进行补偿,就是比如A银行账户如果已经扣减了,但是B银行账户资金增加失败了,那么就得把A银行账户资金给加回去

适用场景:

这种方案说实话几乎很少有人使用,我们用的也比较少,但是也有使用的场景。

因为这个事务回滚实际上是严重依赖于你自己写代码来回滚和补偿了,会造成补偿代码巨大,非常之恶心。

比如说我们,一般来说跟钱相关的,跟钱打交道的,支付、交易相关的场景,我们会用TCC,严格保证分布式事务要么全部成功,要么全部自动回滚,严格保证资金的正确性,在资金上不允许出现问题。

比较适合的场景:除非你是真的一致性要求太高,是你系统中核心之核心的场景,比如常见的就是资金类的场景,那你可以用TCC方案了

你需要自己编写大量的业务逻辑,自己判断一个事务中的各个环节是否ok,不ok就执行补偿/回滚代码。

而且最好是你的各个业务执行的时间都比较短。

但是说实话,一般尽量别这么搞,自己手写回滚逻辑,或者是补偿逻辑,实在太恶心了,那个业务代码很难维护。

6、总结

本篇介绍了什么是分布式事务,然后还介绍了最常用的3种分布式事务方案

但除了上边的方案外,其实还有两阶段提交方案(XA方案)本地消息表等方案。

但是说实话极少有公司使用这些方案,鉴于篇幅所限,不做介绍。后续如果有机会再出篇文章,详细聊聊这两种方案的思路。

这篇关于讲解分布式事务的一篇良心之作的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/700600

相关文章

Python FastAPI+Celery+RabbitMQ实现分布式图片水印处理系统

《PythonFastAPI+Celery+RabbitMQ实现分布式图片水印处理系统》这篇文章主要为大家详细介绍了PythonFastAPI如何结合Celery以及RabbitMQ实现简单的分布式... 实现思路FastAPI 服务器Celery 任务队列RabbitMQ 作为消息代理定时任务处理完整

C# WinForms存储过程操作数据库的实例讲解

《C#WinForms存储过程操作数据库的实例讲解》:本文主要介绍C#WinForms存储过程操作数据库的实例,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、存储过程基础二、C# 调用流程1. 数据库连接配置2. 执行存储过程(增删改)3. 查询数据三、事务处

SpringKafka消息发布之KafkaTemplate与事务支持功能

《SpringKafka消息发布之KafkaTemplate与事务支持功能》通过本文介绍的基本用法、序列化选项、事务支持、错误处理和性能优化技术,开发者可以构建高效可靠的Kafka消息发布系统,事务支... 目录引言一、KafkaTemplate基础二、消息序列化三、事务支持机制四、错误处理与重试五、性能优

Spring事务中@Transactional注解不生效的原因分析与解决

《Spring事务中@Transactional注解不生效的原因分析与解决》在Spring框架中,@Transactional注解是管理数据库事务的核心方式,本文将深入分析事务自调用的底层原理,解释为... 目录1. 引言2. 事务自调用问题重现2.1 示例代码2.2 问题现象3. 为什么事务自调用会失效3

redis+lua实现分布式限流的示例

《redis+lua实现分布式限流的示例》本文主要介绍了redis+lua实现分布式限流的示例,可以实现复杂的限流逻辑,如滑动窗口限流,并且避免了多步操作导致的并发问题,具有一定的参考价值,感兴趣的可... 目录为什么使用Redis+Lua实现分布式限流使用ZSET也可以实现限流,为什么选择lua的方式实现

C++快速排序超详细讲解

《C++快速排序超详细讲解》快速排序是一种高效的排序算法,通过分治法将数组划分为两部分,递归排序,直到整个数组有序,通过代码解析和示例,详细解释了快速排序的工作原理和实现过程,需要的朋友可以参考下... 目录一、快速排序原理二、快速排序标准代码三、代码解析四、使用while循环的快速排序1.代码代码1.由快

Seata之分布式事务问题及解决方案

《Seata之分布式事务问题及解决方案》:本文主要介绍Seata之分布式事务问题及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Seata–分布式事务解决方案简介同类产品对比环境搭建1.微服务2.SQL3.seata-server4.微服务配置事务模式1

Java集合中的List超详细讲解

《Java集合中的List超详细讲解》本文详细介绍了Java集合框架中的List接口,包括其在集合中的位置、继承体系、常用操作和代码示例,以及不同实现类(如ArrayList、LinkedList和V... 目录一,List的继承体系二,List的常用操作及代码示例1,创建List实例2,增加元素3,访问元

Python使用国内镜像加速pip安装的方法讲解

《Python使用国内镜像加速pip安装的方法讲解》在Python开发中,pip是一个非常重要的工具,用于安装和管理Python的第三方库,然而,在国内使用pip安装依赖时,往往会因为网络问题而导致速... 目录一、pip 工具简介1. 什么是 pip?2. 什么是 -i 参数?二、国内镜像源的选择三、如何

Python itertools中accumulate函数用法及使用运用详细讲解

《Pythonitertools中accumulate函数用法及使用运用详细讲解》:本文主要介绍Python的itertools库中的accumulate函数,该函数可以计算累积和或通过指定函数... 目录1.1前言:1.2定义:1.3衍生用法:1.3Leetcode的实际运用:总结 1.1前言:本文将详