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

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

相关文章

计算机毕业设计 大学志愿填报系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点赞 👍 收藏 ⭐评论 📝 🍅 文末获取源码联系 👇🏻 精彩专栏推荐订阅 👇🏻 不然下次找不到哟~Java毕业设计项目~热门选题推荐《1000套》 目录 1.技术选型 2.开发工具 3.功能

集中式版本控制与分布式版本控制——Git 学习笔记01

什么是版本控制 如果你用 Microsoft Word 写过东西,那你八成会有这样的经历: 想删除一段文字,又怕将来这段文字有用,怎么办呢?有一个办法,先把当前文件“另存为”一个文件,然后继续改,改到某个程度,再“另存为”一个文件。就这样改着、存着……最后你的 Word 文档变成了这样: 过了几天,你想找回被删除的文字,但是已经记不清保存在哪个文件了,只能挨个去找。真麻烦,眼睛都花了。看

MySql 事务练习

事务(transaction) -- 事务 transaction-- 事务是一组操作的集合,是一个不可分割的工作单位,事务会将所有的操作作为一个整体一起向系统提交或撤销请求-- 事务的操作要么同时成功,要么同时失败-- MySql的事务默认是自动提交的,当执行一个DML语句,MySql会立即自动隐式提交事务-- 常见案例:银行转账-- 逻辑:A给B转账1000:1.查询

开源分布式数据库中间件

转自:https://www.csdn.net/article/2015-07-16/2825228 MyCat:开源分布式数据库中间件 为什么需要MyCat? 虽然云计算时代,传统数据库存在着先天性的弊端,但是NoSQL数据库又无法将其替代。如果传统数据易于扩展,可切分,就可以避免单机(单库)的性能缺陷。 MyCat的目标就是:低成本地将现有的单机数据库和应用平滑迁移到“云”端

Lua 脚本在 Redis 中执行时的原子性以及与redis的事务的区别

在 Redis 中,Lua 脚本具有原子性是因为 Redis 保证在执行脚本时,脚本中的所有操作都会被当作一个不可分割的整体。具体来说,Redis 使用单线程的执行模型来处理命令,因此当 Lua 脚本在 Redis 中执行时,不会有其他命令打断脚本的执行过程。脚本中的所有操作都将连续执行,直到脚本执行完成后,Redis 才会继续处理其他客户端的请求。 Lua 脚本在 Redis 中原子性的原因

laravel框架实现redis分布式集群原理

在app/config/database.php中配置如下: 'redis' => array('cluster' => true,'default' => array('host' => '172.21.107.247','port' => 6379,),'redis1' => array('host' => '172.21.107.248','port' => 6379,),) 其中cl

基于MySQL实现的分布式锁

概述 在单机时代,虽然不需要分布式锁,但也面临过类似的问题,只不过在单机的情况下,如果有多个线程要同时访问某个共享资源的时候,我们可以采用线程间加锁的机制,即当某个线程获取到这个资源后,就立即对这个资源进行加锁,当使用完资源之后,再解锁,其它线程就可以接着使用了。例如,在JAVA中,甚至专门提供了一些处理锁机制的一些API(synchronize/Lock等)。 但是到了分布式系统的时代,这种

CSP-J基础之数学基础 初等数论 一篇搞懂(一)

文章目录 前言声明初等数论是什么初等数论历史1. **古代时期**2. **中世纪时期**3. **文艺复兴与近代**4. **现代时期** 整数的整除性约数什么样的整数除什么样的整数才能得到整数?条件:举例说明:一般化: 判断两个数能否被整除 因数与倍数质数与复合数使用开根号法判定质数哥德巴赫猜想最大公因数与辗转相除法计算最大公因数的常用方法:举几个例子:例子 1: 计算 12 和 18

ispunct函数讲解 <ctype.h>头文件函数

目录 1.头文件函数 2.ispunct函数使用  小心!VS2022不可直接接触,否则..!没有这个必要,方源一把抓住VS2022,顷刻 炼化! 1.头文件函数 以上函数都需要包括头文件<ctype.h> ,其中包括 ispunct 函数 #include<ctype.h> 2.ispunct函数使用 简述: ispunct函数一种判断字符是否为标点符号的函

深度学习速通系列:深度学习算法讲解

深度学习算法是一系列基于人工神经网络的算法,它们通过模拟人脑处理信息的方式来学习和解决复杂问题。这些算法在图像识别、语音识别、自然语言处理、游戏等领域取得了显著的成就。以下是一些流行的深度学习算法及其基本原理: 1. 前馈神经网络(Feedforward Neural Networks, FNN) 原理:FNN 是最基本的神经网络结构,它由输入层、隐藏层和输出层组成。信息从输入层流向隐藏层,最