首页 > 其他分享 >你讲讲分布式事务问题的几种方案?

你讲讲分布式事务问题的几种方案?

时间:2023-03-19 21:58:28浏览次数:40  
标签:方案 事务 讲讲 系统 回滚 几种 消息 本地 分布式

分布式事务的实现主要有以下 5 种方案:

  • XA 方案
  • TCC 方案
  • 本地消息表
  • 可靠消息最终一致性方案
  • 最大努力通知方案

两阶段提交方案/XA方案

所谓的 XA 方案,即:两阶段提交,有一个事务管理器的概念,负责协调多个数据库(资源管理器)的事务,事务管理器先问问各个数据库你准备好了吗?如果每个数据库都回复 ok,那么就正式提交事务,在各个数据库上执行操作;如果任何其中一个数据库回答不 ok,那么就回滚事务。

这种分布式事务方案,比较适合单块应用里,跨多个库的分布式事务,而且因为严重依赖于数据库层面来搞定复杂的事务,效率很低,不适合高并发的场景。基于 Spring + JTA 就可以实现。

这个方案,我们很少用,一般来说某个系统内部如果出现跨多个库的这么一个操作,是不合规的。

现在微服务,一个大的系统分成几十个甚至几百个服务。一般来说,我们的规定和规范,是要求每个服务只能操作自己对应的一个数据库。

TCC 方案

TCC 的全称是:Try、Confirm、Cancel。

  • Try 阶段:这个阶段说的是对各个服务的资源做检测以及对资源进行锁定或者预留。
  • Confirm 阶段:这个阶段说的是在各个服务中执行实际的操作。
  • Cancel 阶段:如果任何一个服务的业务方法执行出错,那么这里就需要进行补偿,就是执行已经执行成功的业务逻辑的回滚操作。(把那些执行成功的回滚)

这种方案很少人使用,但是也有使用的场景。因为这个事务回滚实际上是严重依赖于你自己写代码来回滚和补偿了,会造成补偿代码巨大,业务代码是很难维护的。

本地消息表

本地消息表其实是国外的 ebay 搞出来的这么一套思想。

这个大概意思是这样的:

  1. A 系统在自己本地一个事务里操作同时,插入一条数据到消息表;
  2. 接着 A 系统将这个消息发送到 MQ 中去;
  3. B 系统接收到消息之后,在一个事务里,往自己本地消息表里插入一条数据,同时执行其他的业务操作,如果这个消息已经被处理过了,那么此时这个事务会回滚,这样保证不会重复处理消息;
  4. B 系统执行成功之后,就会更新自己本地消息表的状态以及 A 系统消息表的状态;
  5. 如果 B 系统处理失败了,那么就不会更新消息表状态,那么此时 A 系统会定时扫描自己的消息表,如果有未处理的消息,会再次发送到 MQ 中去,让 B 再次处理;

这个方案保证了最终一致性,哪怕 B 事务失败了,但是 A 会不断重发消息,直到 B 那边成功为止。

这个方案最大的问题就在于严重依赖于数据库的消息表来管理事务,如果是高并发场景咋办呢?所以一般确实很少用。

可靠消息最终一致性方案

不要用本地的消息表了,直接基于 MQ 来实现事务。比如阿里的 RocketMQ 就支持消息事务。

大概的意思就是:

  1. A 系统先发送一个 prepared 消息到 mq,如果这个 prepared 消息发送失败那么就直接取消操作别执行了;
  2. 如果这个消息发送成功了,那么接着执行本地事务,如果成功就告诉 mq 发送确认消息,如果失败就告诉 mq 回滚消息;
  3. 如果发送了确认消息,那么此时 B 系统会接收到确认消息,然后执行本地的事务;
  4. mq 会自动定时轮询所有 prepared 消息回调你的接口,询问这个消息是不是本地事务处理失败了,所以没发送确认的消息,是继续重试还是回滚?一般来说这里你就可以查下数据库看之前本地事务是否执行,如果回滚了,那么这里也回滚。这个就是避免可能本地事务执行成功了,而确认消息却发送失败了。

这个方案里,要是系统 B 的事务失败了咋办?重试,自动不断重试直到成功,如果实在是不行,要么就是针对重要的资金类业务进行回滚,比如 B 系统本地回滚后,想办法通知系统 A 也回滚;或者是发送报警由人工来手工回滚和补偿。

最大努力通知方案

这个方案的大致意思就是:

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

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

要是系统 B 执行成功就 ok 了;要是系统 B 执行失败了,那么最大努力通知服务就定时尝试重新调用系统 B,反复 N 次,最后还是不行就放弃。

 

参考:

 

标签:方案,事务,讲讲,系统,回滚,几种,消息,本地,分布式
From: https://www.cnblogs.com/xfeiyun/p/17234392.html

相关文章

  • 分布式事务解决方案总结 - 本地消息表
    1,什么是分布式事务?在传统架构中往往是一个单体架构,一个系统就对应一个war包,然后这个系统也只有一个数据库。即一个应用对应一个数据库,此时能满足传统的数据库事务,满足ACID......
  • 分布式事务
    一.XA型事务db-a:1,2,3------rm-adb-b:4,5,6------rm-b      TMdb-c:7,8,9------rm-c rm为资源管理器每个数据库都有TM为分布式事务管理器多......
  • java——Zookeeper学习——zk实现分布式锁了解
                   ......
  • 分布式流处理组件-优化篇:Producer生产调优之核心参数
    ......
  • HDFS分布式文件系统
    目录1️⃣、HDFS的概述1.1、HDFS产出背景及定义1.2、HDFS优缺点1.3、HDFS组成架构1.4、HDFS文件块大小(面试重点)2️⃣、HDFS的Shell操作2.1、基本语法2.2、命令大全2.3、常用命......
  • 几种常用降压集成开关电源芯片
     开关电源类1、LM2575   oscillatorfrequency  开关频率52kHz   常用配套电感100uh 输入15V到24V。最大电流1A。2、LM2596 oscillatorfrequency  ......
  • 【FastDFS分布式文件系统】2.FastDFS架构概述
    上一篇我们讲解了文件的存储机制,有单机存储、共享存储和分布式存储,那么我们的主角---FastDFS就是一个分布式存储机制的文件系统,本篇为大家介绍一下Fast......
  • 分布式搜索-elasticsearch
    学习黑马-SpringCloud微服务技术栈项目的分布式搜索章节自行整理的笔记,方便日后的重构。项目涉及技术知识点是按照集数依次整理,方便日后回来查找。考虑到不是固定的联......
  • 你说你精通Java并发,那给我讲讲J.U.C吧
    J.U.C即java.util.concurrent包,为我们提供了很多高性能的并发类,可以说是java并发的核心。Concurrent包下所有类底层都是依靠CAS操作来实现,而sun.misc.Unsafe为我们提供了......
  • 谈谈你对Java中常用的几种线程池的理解
    为什么使用线程池为每个请求创建一个新线程的开销很大容易引起资源不足,造成浪费使用线程池的风险死锁、资源不足和线程泄漏。死锁当一组进程或线程中的每一个都在......