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

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

相关文章

一篇文章彻底搞懂macOS如何决定java环境

《一篇文章彻底搞懂macOS如何决定java环境》MacOS作为一个功能强大的操作系统,为开发者提供了丰富的开发工具和框架,下面:本文主要介绍macOS如何决定java环境的相关资料,文中通过代码... 目录方法一:使用 which命令方法二:使用 Java_home工具(Apple 官方推荐)那问题来了,

Nginx分布式部署流程分析

《Nginx分布式部署流程分析》文章介绍Nginx在分布式部署中的反向代理和负载均衡作用,用于分发请求、减轻服务器压力及解决session共享问题,涵盖配置方法、策略及Java项目应用,并提及分布式事... 目录分布式部署NginxJava中的代理代理分为正向代理和反向代理正向代理反向代理Nginx应用场景

Java 线程池+分布式实现代码

《Java线程池+分布式实现代码》在Java开发中,池通过预先创建并管理一定数量的资源,避免频繁创建和销毁资源带来的性能开销,从而提高系统效率,:本文主要介绍Java线程池+分布式实现代码,需要... 目录1. 线程池1.1 自定义线程池实现1.1.1 线程池核心1.1.2 代码示例1.2 总结流程2. J

Spring的基础事务注解@Transactional作用解读

《Spring的基础事务注解@Transactional作用解读》文章介绍了Spring框架中的事务管理,核心注解@Transactional用于声明事务,支持传播机制、隔离级别等配置,结合@Tran... 目录一、事务管理基础1.1 Spring事务的核心注解1.2 注解属性详解1.3 实现原理二、事务事

MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决

《MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决》MyBatis默认开启一级缓存,同一事务中循环调用查询方法时会重复使用缓存数据,导致获取的序列主键值均为1,... 目录问题原因解决办法如果是存储过程总结问题myBATis有如下代码获取序列作为主键IdMappe

Java中实现对象的拷贝案例讲解

《Java中实现对象的拷贝案例讲解》Java对象拷贝分为浅拷贝(复制值及引用地址)和深拷贝(递归复制所有引用对象),常用方法包括Object.clone()、序列化及JSON转换,需处理循环引用问题,... 目录对象的拷贝简介浅拷贝和深拷贝浅拷贝深拷贝深拷贝和循环引用总结对象的拷贝简介对象的拷贝,把一个

详解Spring中REQUIRED事务的回滚机制详解

《详解Spring中REQUIRED事务的回滚机制详解》在Spring的事务管理中,REQUIRED是最常用也是默认的事务传播属性,本文就来详细的介绍一下Spring中REQUIRED事务的回滚机制,... 目录1. REQUIRED 的定义2. REQUIRED 下的回滚机制2.1 异常触发回滚2.2 回

Spring 中的切面与事务结合使用完整示例

《Spring中的切面与事务结合使用完整示例》本文给大家介绍Spring中的切面与事务结合使用完整示例,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考... 目录 一、前置知识:Spring AOP 与 事务的关系 事务本质上就是一个“切面”二、核心组件三、完

Redis实现分布式锁全过程

《Redis实现分布式锁全过程》文章介绍Redis实现分布式锁的方法,包括使用SETNX和EXPIRE命令确保互斥性与防死锁,Redisson客户端提供的便捷接口,以及Redlock算法通过多节点共识... 目录Redis实现分布式锁1. 分布式锁的基本原理2. 使用 Redis 实现分布式锁2.1 获取锁

Unity新手入门学习殿堂级知识详细讲解(图文)

《Unity新手入门学习殿堂级知识详细讲解(图文)》Unity是一款跨平台游戏引擎,支持2D/3D及VR/AR开发,核心功能模块包括图形、音频、物理等,通过可视化编辑器与脚本扩展实现开发,项目结构含A... 目录入门概述什么是 UnityUnity引擎基础认知编辑器核心操作Unity 编辑器项目模式分类工程