【07】分布式事务解决方案

1、事务简介

  • 事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。
  • 在关系数据库中,一个事务由一组SQL语句组成。事务应该具有ACID四个特性:原子性一致性隔离性持久性
  • 任何事务机制在实现时,都应该考虑事务的ACID特性,包括:本地事务、分布式事务。

1.1 本地事务

  • @Transational
    • 大多数场景下,我们的应用都只需要操作单一的数据库,这种情况下的事务称之为本地事务(Local Transaction)。本地事务的ACID特性是数据库直接提供支持。
    • 本地事务应用架构如下所示:
      本地事务架构图
  • 在JDBC编程中,我们通过java.sql.Connection对象来开启、关闭或者提交事务。
    • 代码如下所示:
      Connection conn = ... //获取数据库连接
      conn.setAutoCommit(false); //开启事务
      try{
         //...执行增删改查sql
         conn.commit(); //提交事务
      }catch (Exception e) {
        conn.rollback();//事务回滚
      }finally{
         conn.close();//关闭链接
      

1.2 分布式事务典型场景

  • 当下互联网发展如火如荼,绝大部分公司都进行了数据库拆分和服务化(SOA)。在这种情况下,完成某一个业务功能可能需要横跨多个服务,操作多个数据库。
  • 这就涉及到了分布式事务,需要操作的资源位于多台资源服务器上,而应用需要保证对于多个资源服务器数据的操作,要么全部成功,要么全部失败。本质上来说,分布式事务就是为了保证不同资源服务器的数据一致性。
1.2.1 跨库事务
  • 跨库事务指的是,应用的某个功能需要操作多个库,不同的库中存储这不同的业务数据。
  • 下图演示了一个服务同时操作两个库的情况:
    跨库事务
1.2.2 分库分表
  • 通常一个库数据量比较大或者预期未来的数据量比较大,都会进行水平拆分,也就是分库分表。
  • 如下图,将数据库B拆分成了2个库:
    分库分表
  • 对于分库分表的情况,一般开发人员都会使用一些数据库中间件来降低sql操作的复杂性
  • 例如,对于sql:insert into user(id,name) values (1,"张三"),(2,"李四")。这条sql是操作单库的语法,单库情况下,可以保证事务的一致性。
  • 但是由于现在进行了分库分表,开发人员希望将1号记录插入分库1,2号记录插入分库2。所以数据库中间件要将其改写为2条sql,分别插入两个不同的分库,此时要保证两个库要不都成功,要不都失败,因此基本上所有的数据库中间件都面临着分布式事务的问题。
1.2.3 服务化
  • 微服务架构是目前比较比较火的概念。例如:某个应用同时操作了9个数据库,这样的应用业务逻辑必然非常复杂,对于开发人员是极大的挑战,应该拆分成不同的独立服务,以简化业务逻辑。拆分后,独立服务之间通过RPC框架来进行远程调用,实现彼此的通信。
  • 下图演示了3个服务之间彼此调用的架构:
    服务化
  • Service A完成某个功能需要直接操作数据库,同时又需要调用Service B和Service C,而Service B又同时操作了2个数据库,Service C也操作了一个库。需要保证这些跨服务的对多个数据库的操作要不都成功,要不都失败,实际上这可能是最典型的分布式事务场景。

2、分布式事务理论基础

  • 解决分布式事务,也有相应的规范和协议。分布式事务相关的协议有2PC3PC
  • 由于3PC(三阶段提交协议)非常难实现,目前市面主流的分布式事务解决方案都是2PC协议。
  • 有些文章在分析2PC时,几乎都会用TCC两阶段的例子,第一阶段try,第二阶段完成confirm或cancel。其实2PC并不是专为实现TCC设计的,2PC具有普适性——协议一样的存在,目前绝大多数分布式解决方案都是以2PC(两阶段提交协议)为基础的。
  • TCC(Try-Confirm-Cancel) 实际上是服务化的两阶段提交协议。

2.1 2PC两阶段提交协议

  • 2PC(Two-Prepare-Commit):分为Prepare(预处理)和Commit(提交)两个阶段。
    • Prepare:提交事务请求
      prepare
      • 首先协调者向所有参与者发送事务请求,询问是否可以执行事务操作,然后等待各个参与者的响应;
      • 然后:各个参与者接收到协调者事务请求后,执行事务操作(例如:更新一个关系型数据库表中的记录),并将 Undo(更新前的状态) 和 Redo(更新后的状态) 信息记录事务日志中。
      • 最后:如果参与者成功执行了事务并写入 Undo 和 Redo 信息,则向协调者返回 YES 响应,否则返回 NO 响应。当然,参与者也可能宕机,从而不会返回响应。
    • Commit:执行事务提交/回滚
    • 正常提交事务:
      正常事务提交
      • 首先:协调者向所有参与者发送 Commit 请求。
      • 然后:参与者收到 Commit 请求后,执行事务提交,提交完成后释放事务执行期占用的所有资源。
      • 其次:参与者执行事务提交后向协调者发送 Ack 反馈响应。
      • 最后:协调者接收到所有参与者的 Ack 响应后,完成事务提交。
    • 回滚事务:
      • 在执行 Prepare 步骤过程中,如果某些参与者执行事务失败、宕机或与协调者之间的网络中断,那么协调者就无法收到所有参与者的 YES 响应,或者某个参与者返回了 No 响应,此时,协调者就会进入回退流程,对各个参与者的事务进行回滚操作。
        回滚事务
      • 首先:协调者向所有参与者发送 Rollback 请求。
      • 然后:参与者收到 Rollback 后,使用 Prepare 阶段的 Undo 日志执行事务回滚,完成后释放事务执行期占用的所有资源。
      • 其次: 参与者执行事务回滚后向协调者发送 Ack 响应。
      • 最后:接收到所有参与者的 Ack 响应后,完成事务回滚。

2.2 2PC存在的问题

  • 同步阻塞:参与者在等待协调者的指令时,其实是在等待其他参与者的响应,在此过程中,参与者是无法进行其他操作的,也就是阻塞了其运行。 倘若参与者与协调者之间网络异常导致参与者一直收不到协调者信息,那么会导致参与者一直阻塞下去。
  • 单点障碍:在 2PC 中,一切请求都来自协调者,所以协调者的地位是至关重要的,如果协调者宕机,那么就会使参与者一直阻塞并一直占用事务资源。
  • 数据不一致:Commit 事务过程中,Commit 请求 或 Rollback 请求可能会因为协调者宕机或协调者与参与者网络问题丢失,那么就导致了部分参与者没有收到 Commit/Rollback 请求,而其他参与者则正常收到执行了 Commit/Rollback 操作,没有收到请求的参与者则继续阻塞。这时,参与者之间的数据就不再一致了。
  • 环境可靠性依赖:协调者 Prepare 请求发出后,等待响应,然而如果有参与者宕机或与协调者之间的网络中断,都会导致协调者无法收到所有参与者的响应,那么在 2PC 中,协调者会等待一定时间,然后超时后,会触发事务中断,在这个过程中,协调者和所有其他参与者都是出于阻塞的。这种机制对网络问题常见的现实环境来说太苛刻了。

3、分布式事务实现的4种模式

3.1 AT模式(auto transcation)

  • AT 模式是一种无侵入的分布式事务解决方案,阿里的Seata框架,实现了该模式。
  • 在 AT 模式下,用户只需关注自己的“业务 SQL”,用户的 “业务 SQL” 作为一阶段,Seata 框架会自动生成事务的二阶段进行提交和回滚操作。
    阶段图
  • AT 模式如何做到对业务的无侵入 :
    • AT 模式的一阶段、二阶段提交和回滚均由 Seata 框架自动生成,用户只需编写“业务 SQL”,便能轻松接入分布式事务,AT 模式是一种对业务无任何侵入的分布式事务解决方案。
    • 一阶段:
      • 在一阶段,Seata 会拦截“业务 SQL”,首先解析 SQL 语义,找到“业务 SQL”要更新的业务数据,在业务数据被更新前,将其保存成before image,然后执行“业务 SQL”更新业务数据,在业务数据更新之后,再将其保存成after image,最后生成行锁。
      • 以上操作全部都在一个数据库事务内完成,这样保证了一阶段操作的原子性。
        一阶段
    • 二阶段提交:
      • 二阶段如果是提交的话,因为“业务 SQL”在一阶段已经提交至数据库, 所以 Seata 框架只需将一阶段保存的快照数据和行锁删掉,完成数据清理即可。
        二阶段提交
    • 二阶段回滚:
      • 二阶段如果是回滚的话,Seata 就需要回滚一阶段已经执行的“业务 SQL”,还原业务数据。回滚方式便是用“before image”还原业务数据;但在还原前要首先要校验脏写,对比“数据库当前业务数据”和 “after image”,如果两份数据完全一致就说明没有脏写,可以还原业务数据,如果不一致就说明有脏写,出现脏写就需要转人工处理。
        二阶段回滚

3.2 TCC 模式

  • 侵入性比较强, 并且需要自己实现相关事务控制逻辑;
  • 在整个过程基本没有锁,性能更强;
  • TCC 模式需要用户根据自己的业务场景实现 TryConfirmCancel 三个操作;
    • 事务发起方在一阶段执行 Try 方法,
    • 在二阶段提交执行 Confirm 方法,二阶段回滚执行 Cancel 方法。
  • TCC 三个方法描述:
    • Try:资源的检测和预留;
    • Confirm:执行的业务操作提交,要求 Try 成功 Confirm 一定要能成功;
    • Cancel:预留资源的释放;
      TCC模式
  • TCC的实践经验:
    • 蚂蚁金服TCC实践,总结以下注意事项:
      • 业务模型分2阶段设计
      • 并发控制
      • 允许空回滚
      • 防悬挂控制
      • 幂等控制
    • 1、TCC 设计 – 业务模型分 2 阶段设计:
      • 用户接入 TCC 模式,最重要的事情就是考虑如何将业务模型拆成 2 阶段,实现成 TCC 的 3 个方法,并且保证 Try 成功 Confirm 一定能成功。相对于 AT 模式,TCC 模式对业务代码有一定的侵入性,但是 TCC 模式无 AT 模式的全局行锁,TCC 性能会比 AT 模式高很多。
      • 以“扣钱”场景为例,在接入 TCC 前,对 A 账户扣钱,只需一条更新账户余额的 SQL 便能完成;但是在接入 TCC 之后,用户就需要考虑如何将原来一步就能完成的扣钱操作,拆成两阶段,实现成三个方法,并且保证一阶段 Try 成功的话 二阶段 Confirm 一定能成功。
        示例
      • 如上图所示,Try 方法作为一阶段的准备方法,需要做资源的检查和预留。在扣钱场景下,Try 要做的事情是就是检查账户余额是否充足,预留转账资金,预留的方式就是冻结 A 账户的 转账资金。Try 方法执行之后,账号 A 余额虽然还是 100,但是其中 30 元已经被冻结了,不能被其他事务使用。
      • 二阶段 Confirm 方法执行真正的扣钱操作。Confirm 会使用 Try 阶段冻结的资金,执行账号扣款。Confirm 方法执行之后,账号 A 在一阶段中冻结的 30 元已经被扣除,账号 A 余额变成 70 元 。
      • 如果二阶段是回滚的话,就需要在 Cancel 方法内释放一阶段 Try 冻结的 30 元,使账号 A 的回到初始状态,100 元全部可用。
    • 2、TCC 设计 – 允许空回滚:
      允许空回滚
      • Cancel 接口设计时需要允许空回滚。在 Try 接口因为丢包时没有收到,事务管理器会触发回滚,这时会触发 Cancel 接口,这时 Cancel 执行时发现没有对应的事务 xid 或主键时,需要返回回滚成功。让事务服务管理器认为已回滚,否则会不断重试,而 Cancel 又没有对应的业务数据可以进行回滚。
    • 3、TCC 设计 – 防悬挂控制:
      防悬挂控制
      • 悬挂的意思是:Cancel 比 Try 接口先执行,出现的原因是 Try 由于网络拥堵而超时,事务管理器生成回滚,触发 Cancel 接口,而最终又收到了 Try 接口调用,但是 Cancel 比 Try 先到。按照前面允许空回滚的逻辑,回滚会返回成功,事务管理器认为事务已回滚成功,则此时的 Try 接口不应该执行,否则会产生数据不一致,所以我们在 Cancel 空回滚返回成功之前先记录该条事务 xid 或业务主键,标识这条记录已经回滚过,Try 接口先检查这条事务xid或业务主键如果已经标记为回滚成功过,则不执行 Try 的业务操作。
    • 4、TCC 设计 – 幂等控制:
      幂等控制
      • 幂等性的意思是:对同一个系统,使用同样的条件,一次请求和重复的多次请求对系统资源的影响是一致的。因为网络抖动或拥堵可能会超时,事务管理器会对资源进行重试操作,所以很可能一个业务操作会被重复调用,为了不因为重复调用而多次占用资源,需要对服务设计时进行幂等控制,通常我们可以用事务 xid 或业务主键判重来控制。

3.3 Saga模式

  • Saga 理论出自 Hector & Kenneth 1987发表的论文 Sagas。
  • Saga模式的实现,是长事务解决方案。
    Saga模式
  • Saga 是一种补偿协议,在 Saga 模式下,分布式事务内有多个参与者,每一个参与者都是一个冲正补偿服务,需要用户根据业务场景实现其正向操作和逆向回滚操作。
    • 分布式事务执行过程中,依次执行各参与者的正向操作,如果所有正向操作均执行成功,那么分布式事务提交。如果任何一个正向操作执行失败,那么分布式事务会退回去执行前面各参与者的逆向回滚操作,回滚已提交的参与者,使分布式事务回到初始状态。
    • Saga 正向服务与补偿服务也需要业务开发者实现。因此是业务入侵的。
    • Saga 模式下分布式事务通常是由事件驱动的,各个参与者之间是异步执行的,Saga 模式是一种长事务解决方案。
      冲正
  • Saga 模式使用场景:
    • Saga 模式适用于业务流程长且需要保证事务最终一致性的业务系统,Saga 模式一阶段就会提交本地事务,无锁、长流程情况下可以保证性能。
    • 事务参与者可能是其它公司的服务或者是遗留系统的服务,无法进行改造和提供 TCC 要求的接口,可以使用 Saga 模式。
  • Saga模式的优势是:
    • 一阶段提交本地数据库事务,无锁,高性能;
    • 参与者可以采用事务驱动异步执行,高吞吐;
    • 补偿服务即正向服务的“反向”,易于理解,易于实现;

3.4 XA模式

  • XA是X/Open DTP组织(X/Open DTP group)定义的两阶段提交协议,XA被许多数据库(如Oracle、DB2、SQL Server、MySQL)和中间件等工具(如CICS 和 Tuxedo)本地支持 。
  • X/Open DTP模型(1994)包括应用程序(AP)、事务管理器(TM)、资源管理器(RM)。
  • XA接口函数由数据库厂商提供。XA规范的基础是两阶段提交协议2PC。
  • JTA(Java Transaction API) 是Java实现的XA规范的增强版 接口。
  • 在XA模式下,需要有一个[全局]协调器,每一个数据库事务完成后,进行第一阶段预提交,并通知协调器,把结果给协调器。协调器等所有分支事务操作完成、都预提交后,进行第二步;
  • 第二步:协调器通知每个数据库进行逐个commit/rollback。
  • 其中,这个全局协调器就是XA模型中的TM角色,每个分支事务各自的数据库就是RM。
    MySQL 提供的XA实现(https://dev.mysql.com/doc/refman/5.7/en/xa.html )
  • XA模式下的 开源框架有atomikos,其开发公司也有商业版本。
  • XA模式缺点:事务粒度大。高并发下,系统可用性低。因此很少使用。

3.5 (AT、TCC、Saga、XA)模式分析

  • 四种分布式事务模式,分别在不同的时间被提出,每种模式都有它的适用场景。
    • AT 模式是无侵入的分布式事务解决方案,适用于不希望对业务进行改造的场景,几乎0学习成本。
    • TCC 模式是高性能分布式事务解决方案,适用于核心系统等对性能有很高要求的场景。
    • Saga 模式是长事务解决方案,适用于业务流程长且需要保证事务最终一致性的业务系统,Saga 模式一阶段就会提交本地事务,无锁,长流程情况下可以保证性能,多用于渠道层、集成层业务系统。事务参与者可能是其它公司的服务或者是遗留系统的服务,无法进行改造和提供 TCC 要求的接口,也可以使用 Saga 模式。
    • XA模式是分布式强一致性的解决方案,但性能低而使用较少。
  • 分布式事务本身就是一个技术难题,业务中具体使用哪种方案还是需要不同的业务特点自行选择,但是我们也会发现,分布式事务会大大的提高流程的复杂度,会带来很多额外的开销工作,「代码量上去了,业务复杂了,性能下跌了」。所以,当我们真实开发的过程中,能不使用分布式事务就不使用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/799401.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

mac生成.dmg压缩镜像文件

mac生成.dmg压缩镜像文件 背景准备内容步骤1,找一个文件夹2,制作application替身1,终端方式2,黄金右手方式 3,.app文件放入文件夹4,制作.dmg压缩镜像文件5,安装.dmg 总结 背景 为绕开App Store…

纯css实现语音播报动画效果

先来看看效果图 黑色以下代码 background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAAAYCAYAAAAF6fiUAAAAAXNSR0IArs4c6QAAAARzQklUCAgICHwIZIgAAAO8SURBVGiB1ZlPaBxVHMe/v7fbkmUZErRs9/1moUtYBBfxklZR8aYg5KAgvcT25MFDvUhPTaGnHoKIlOpJ0VsPUvAgKNjSS0EPAVGKya…

防火墙综合实验之NAT和智能选路

目录 前言: 一、实验题目 二、实验操作 需求一 需求二 需求三 需求四、需求五 需求六 需求七 ​编辑 需求八 需求九 需求十 需求十一 三、需求测试 前言: 本篇文章是延续上一篇文章,简单来说就是防火墙实验的完善和延续&#…

Zabbix6.0监控Freeswitch状态

一、前提环境说明 1、最终实现Freeswitch监控指标信息: 2、环境需求: (1)需要使用Zabbix6.0及以上 (2)需要使用zabbix_agent2 二、实现步骤 1、zabbix_agent2添加监控键值 cat /etc/zabbix/conf.d/fr…

唯众物联网综合实训台 物联网实验室建设方案

物联网综合实训装置 物联网工程应用综合实训台是我公司针对职业院校物联网行业综合技能型人才培养,综合运用传感器技术、RFID技术、接口控制技术、无线传感网技术、Android应用开发等,配合实训台上的433M无线通信设备、ZigBee节点、射频设备、控制设备、…

CoT-SC论文速读

1.论文速读 本文提出了一个重要的Decoder策略为:“Self-Consistency”,并将其用在CoT的Prompt工作中。 该策略作用:让LLM在处理复杂问题时,让他尝试多个推理路径,每一个推理路径都是一次CoT(Chain of Thought&#x…

解决回溯算法之切割问题(leetcode--分割回文串)

文章目录 1.问题描述2.做题思路(关键是画出对于的二叉树图)3.代码实现 1.问题描述 2.做题思路(关键是画出对于的二叉树图) 1.思考从起始串的分割方案, 有a ,aa, aab三种方式 2.————————————剩余ab,b,空(接下来对ab,b同样的方式进行分割) 3.…

【Linux】centos7安装PHP7.4报错:libzip版本过低

问题描述 configure: error: Package requirements (libzip > 0.11 libzip ! 1.3.1 libzip ! 1.7.0) were not met: checking for libzip > 0.11 libzip ! 1.3.1 libzip ! 1.7.0... no configure: error: Package requirements (libzip > 0.11 libzip ! 1.3.1 libzi…

星辰计划02-独特视角的spring动态代理

承接上一文 动态代理 ,这里探究spring 动态代理 会话1:spring动态代理 quick start 👧哥哥,哥哥,spring 怎么去搞动态代理的呢👨 来来来,听我细细来说 quick start通过Spring的 ProxyFactory…

【高中数学/幂函数】比较a=2^0.3,b=3^0.2,c=7^0.1的大小

【问题】 比较a2^0.3,b3^0.2,c7^0.1的大小 【解答】 a2^0.32^3/10(2^3)^1/108^1/10 b3^0.23^2/10(3^2)^1/109^1/10 c7^0.17^1/10 由于yx^1/10在x正半轴是增函数,底数大的得数就大。 因为9>8>7,所以b>a>c 【图像】 在图像上绘出曲线yx^1/10&…

C++初阶:类和对象(二)

✨✨所属专栏:C✨✨ ✨✨作者主页:嶔某✨✨ 类的默认成员函数 默认成员函数就是用户没有显式实现,编译器会⾃动⽣成的成员函数称为默认成员函数。⼀个类,我们不写的情况下编译器会默认⽣成以下6个默认成员函数,需要注…

报文对比工具

如果有报文对比需求,可以通过以下步骤实现: ①通过在线 XML排序、压缩、格式化 网站 排序后格式化数据 http://www.bejson.com/otherformat/xmlsort/ 访问速度快,操作直观, 1.原始xml数据 2.排序 3.格式化 ②N比对数据是否一…

哥德巴赫猜想c++

方法一 #include<bits/stdc.h> using namespace std; //定义函数&#xff0c;判断素数 bool sushu(int n){bool rtrue;//先假设是素数&#xff0c;即真//循环因子范围&#xff0c;找到一个因子就不是素数for(int i2;i<sqrt(n);i){//判断2~n的根号是否素数if(n%i0){//…

翁恺-C语言程序设计-05-3. 求a的连续和

05-3. 求a的连续和 输入两个整数a和n&#xff0c;a的范围是[0,9]&#xff0c;n的范围是[1,8]&#xff0c;求数列之和S aaaaaa…aaa…a&#xff08;n个a&#xff09;。如a为2、n为8时输出的是222222…22222222的和。 输入格式&#xff1a; 输入在一行中给出两个整数&#xf…

Hdfs3.x新特性详解

作者&#xff1a;九月 HDFS Disk Balancer(磁盘均衡器) HDFS Disk Balancer与HDFS Balancer的区别 两者都是实现负载均衡功能。 HDFS Balancer是之前Hadoop2.x中本身存在的&#xff0c;主要是多个DataNode节点之间的数据的平衡。 HDFS Disk Balancer是Hadoop3中新出现的&…

融云:换头像=换人设?社交应用中隐秘而重要的「用户信息管理」

当代年轻人失眠三大原因&#xff0c;最近新上的《喜人奇妙夜》帮你找到了—— 基金绿了、吵架输了、前任头像换了。 当你半夜翻看前任的社交账号&#xff0c;一场盛大的失眠就开始了&#xff0c;就算古希腊掌柜睡眠的神躺你旁边也不好使。即便 Ta 没有更新内容&#xff0c;昵…

Linux RTL8111/RTL8168 不能联网 / 最新版驱动下载安装

注&#xff1a; 机翻&#xff0c;未校对。 如何让 Realtek RTL8111/RTL8168 在 Linux 下工作 这篇文章于 2016 年 8 月在我原来的博客上发布。尽管如今 Linux 下的 RTL8111/RTL8168 网络接口的情况变得越来越稳定&#xff0c;但它们仍然会导致数据包丢失或网络连接不稳定等问题…

C1W1.Assignment: Logistic Regression

理论课&#xff1a;C1W1.Sentiment Analysis with Logistic Regression 文章目录 前期准备导入包导入数据处理推文文本 Part 1: Logistic regressionPart 1.1: Sigmoid实现 sigmoid 函数Logistic regression: regression and a sigmoid Part 1.2 Cost function and GradientUp…

自动驾驶-端到端分割任务

上采样 bed of nails interpolation transposed convolutions 1. 上采样 (Upsampling) 上采样是一种技术&#xff0c;用于增加数据集中的样本数量或是提高信号的分辨率。在图像处理中&#xff0c;上采样通常指的是增加图像的像素数量&#xff0c;从而使图像变得更大。这可…

【Android安全】Ubuntu 下载、编译 、刷入Android-8.1.0_r1

0. 环境准备 Ubuntu 16.04 LTS&#xff08;预留至少95GB磁盘空间&#xff0c;实测占94.2GB&#xff09; Pixel 2 XL 要买欧版的&#xff0c;不要美版的。 欧版能解锁BootLoader、能刷机。 美版IMEI里一般带“v”或者"version"&#xff0c;这样不能解锁BootLoader、…