【学习笔记】DTM分布式事务

分布式事务是什么

本文的分布式事务指的是DTM下的分布式事务。

分布式事务有两类,这里指的是跨数据库、跨服务的分布式事务。

分布式事务指事务的发起者、资源及资源管理器和事务协调者分别位于分布式系统的不同节点之上。

CAP理论

  • C(一致性):指分布式节点中数据一致。
  • A(可用性):指无论何时向分布式系统发送请求都能响应。
  • P(分区容错性):发生网络分区时会产生脑裂问题,分区容错性就是解决脑裂问题。

在CAP理论中,C、A、P只能满足其中的一种或两种,无法同时满足三种情况。

file

BASE理论

  • BA(基本可用):极端情况下牺牲部分可用性,只需满足基本可用即可,但不等于完全不可用。
  • S(软状态):允许数据存在中间态,即允许数据传输存在延迟。
  • E(最终一致性):无需强一致性,在一段时间后可以满足一致性即可。

无法保证强一致性

分布式事务中一致性最强的是XA模式(见下面事务模式-XA),XA是采用两个阶段执行事务的:准备阶段(prepare)和提交/回滚阶段(commit/rollback)。

可是开始事务操作以及提交/回滚阶段并不能保证所有RM(资源管理者,可以理解成数据库实例)都能同步进行,所以不能保证强一致性。

file

如上图所示,隔离级别为可重复读,这里查询数据的时机是:微服务2中的RM事务已提交,微服务1中的RM未提交。此时查询到的结果为A+B+30,数据不一致。

如果隔离级别为序列化,也会存在不一致的情况,如下图所示:

file

上图中隔离级别为序列化,查询时机为:微服务1中RM开启事务,微服务2中RM为开启事务,返回结果为A+B-30,数据不一致。

理论上的强一致性

理论上可以在读已提交隔离级别实现强一致性,需要为读加上写锁,即select for update的形式。

这样子,读的数据要么都是事务启动前的,要么都是事务提交后的,不会出现一个读取到的是事务启动前的数据、一个读取到的是事务提交后的数据的情况。

但是这样子对性能影响很大。

最终一致性

分布式事务一致性不能保证的情况发生在分布式事务进行当中。当事务完成后是可以保证一致性的,这里的一致性还包括数据库完整性。

以下是各个分布式事务模式中,一致性强度的分类,一致性由强到弱分别是:

XA事务>TCC>二阶段消息>SAGA

其中,XA事务是通过commit提交事务的,而TCC是在业务层通过confirm提交事务的,理论上来说XA的不一致性时间要比TCC的短。

异常与子事务屏障

NPC问题

NPC是Network Delay、Process Pause、Clock Drift的简写,是分布式系统会遇到的重大挑战,其中对分布式系统影响最大的是NP

  • Network Delay:由于网络环境复杂,不可避免的会出现网络延迟的问题。
  • Process Pause:由GC机制等各种情况导致的进程暂停,特别是云服务中可以利用进程暂停将一台主机迁移至另一台主机,进程暂停时间可能会长达数十分钟。
  • Clock Drift:计算机中计时会存在误差,在分布式系统中就会导致每个节点之间时间不一致的问题。为了同一时间,一般会使用NTP服务统一各节点的时间,但这样会导致节点的时间突然向前或先后偏移。

异常分类

以分布式事务TCC为例,分布式系统的两大难题:

  • 悬挂:如果发生网络乱序,导致comfirm/cancel操作先执行,try操作后执行,那么事务将永远无法完成。解决方法:在执行try操作时判断事务是否执行过comfirm/cancel,如果执行过则拒绝执行try操作,直接返回。
  • 空补偿:try执行失败触发cancel补偿,但是由于网络乱序,导致cancel请求比try请求先到达,从而导致先执行cancel操作,这就是空补偿。解决方法:在执行cancel时判断事务是否执行过try,如果没有则拒绝执行cancel操作,直接返回。

此外,发生请求失败,重试过程中也会遇到重复请求的情况,如果请求不幂等,会导致异常。

  • 幂等:无论请求多少次,请求的结果都是相同的,不会对原有数据进行改变。

因为空补偿、悬挂、重复请求都跟NP有关,我们把他们统称为子事务乱序问题。在业务处理中,需要小心处理好这三种问题,否则会出现错误数据。

大众方案的问题

大众对异常解决方案是:允许空补偿和防悬挂。

  • 允许空补偿:因为补偿请求之前肯定有事务执行请求,因此可以允许空补偿,但是要标记空补偿。
  • 防悬挂:在执行事务前,要判断这个事务是否补偿过,如果补偿过要拒绝执行事务,避免悬挂。

这种处理方法在极端场景下会出问题:假如执行事务和进行补偿的是两个节点,执行事务的节点在执行过程中发送进程暂停(NPC中的P),补偿操作的节点正常执行。导致补偿操作比执行事务操作先完成,这又导致了空悬挂问题。

PS:幂等控制如果也采用“先查再改”,也是一样很容易出现类似的问题。解决这一类问题的关键点是要利用唯一索引,“以改代查”来避免竞态条件。

DTM的幂等控制原理是,插入一条有关请求的唯一主键,如果插入失败直接返回成功,不用执行后续业务流程,否则将执行业务流程。

子事务屏障

dtm的一项技术,在dtm层面解决异常问题,具体效果如下图所示:

file

子事务屏障会管理TCC、SAGA、事务消息等,也可以扩展到其他领域

原理

子事务屏障技术的原理是,在本地数据库,建立分支操作状态表dtm_barrier,唯一键为全局事务id-分支id-分支操作(try|confirm|cancel)

具体操作如下:

  1. 开启本地事务
  2. 对于任意操作(try/comfirm/cancle):在表中插入唯一键,如果插入失败则提交事务返回成功(常见的幂等控制法)
  3. 对于补偿操作(cancle):在表中插入try的键,如果插入成功,提交事务返回成功
  4. 调用业务逻辑,如果执行成功则提交事务返回成功,否则回滚事务并返回失败

这样可以满足空补偿、悬挂和幂等问题:

  • 解决空补偿问题:在执行cancle时,会在表中插入cancle的唯一键后插入try的唯一键,如果插入try成功就代表没有执行try,就不执行补偿了,从而解决空补偿问题。
  • 解决悬挂问题:在执行try时,会在表中插入try的唯一键。如果cancle在try前执行,表中就存在了try的唯一键,那try就不会被执行。
  • 解决幂等问题:由于每个操作都会在表中插入唯一键,就保证真正执行只会执行一次,保证了操作的幂等性。

竞争分析

如果try和cancle在同一时刻执行,那么会有一个先开启事务,没开启事务的要等到前一个事务执行完成在开启事务。

  • try先cancle后:正常执行
  • cancle先try后:可能会有空补偿和悬挂问题,由于子事务屏障的存在,不会发生空补偿和悬挂问题
  • 发生宕机:会进行重试

最终成功

最终成功指的是,允许操作暂时性失败,但是通过重试等操作,最终使操作成功。

最终成功的情况

最终成功的情况包括以下方面

  • 二阶段消息中的分支操作
  • SAGA中的回滚操作
  • TCC的Confirm和Cancel操作

业务中需要保证以上的操作能正常执行,在业务逻辑上是可以最终成功的。

为什么要最终成功

在SAGA中,回滚假如不能最终成功,那么会陷入一个很尴尬的局面:该事物既无法提交,又无法回滚,使得事务不能正常进行。

分布式事务无法解决这类问题,所以要在业务代码中保证回滚的最终成功。

应用如何设计

😰没看懂

  • 二阶段消息的分支操作是最终成功的,因为二阶段消息不支持回滚。如果您需要回滚,那么请采用其他事务模式
  • SAGA事务如果有些正向操作是无法回滚的,那么您可以用普通非并发的SAGA,将可回滚的分支Ri放在前面,不可回滚的分支Ni放在后面。如果分支Ri正向操作失败,则会回滚Ri,一旦到了Ni,保证Ni的正向操作最终成功,这样也能够保证SAGA事务的正确运行
  • TCC事务的Confirm/Cancel是最终成功的,一般的设计是在TCC的Try阶段预留资源,检查约束条件,然后在Confirm阶段修改数据,在Cancel阶段释放预留的资源。经过精心的设计,能够在业务逻辑上保证Confirm/Cancel的最终成功
注意点

在实际的业务应用中,可能会出现某些应用bug,导致要求最终成功的操作,一直无法成功,导致数据一直无法达到最终一致。建议开发者对全局事务表进行监控,发现重试超过3次的事务,发出报警,由运维人员找开发手动处理,参见dtm的运维

XA

是什么

一种分布式事务的规范,主要定义了两个角色:TM(事务管理器)和RM(资源管理器)。

一个XA事务包含两个阶段:

  1. 准备阶段(prepare):当RM完成本地事务时,向TM发送prepare命令
  2. 提交阶段(commit/rollback)当所有RM都准备好了,则进行commit;反之则rollback。

本地数据库如何支持XA

-- 第一阶段 准备XA start '4fPqCNTYeSG' -- 开启一个 xa 事务UPDATE `user_account` SET `balance`=balance + 30,`update_time`='2021-06-09 11:50:42.438' WHERE user_id = '1'XA end '4fPqCNTYeSG'XA prepare '4fPqCNTYeSG' -- 此调用之前,连接断开,那么事务会自动回滚-- 当所有的参与者完成了prepare,就进入第二阶段 提交xa commit '4fPqCNTYeSG'

好处与坏处

  • 简单易理解
  • 开发较容易,回滚之类的操作,由底层数据库自动完成
  • 对资源进行了长时间的锁定,并发度低,不适合高并发的业务

SAGA

SAGA分布式事务模式的精髓是:将一个长事务拆分成多个短事务,由SAGA协调器负责协调。如果所有短事务完成,则全局事务完成,反之则由当前异常的短事务开始反向按顺序进行补偿操作。

SAGA的事务操作是服务端编排的。

拆分为子事务

有一个银行转账的分布式事务:A向B转账30元

SAGA事务会拆成一下事务:

  • A转出事务:A账户中-30元
  • A转出补偿事务:在执行过A转出事务的数据库中将A账户+30元
  • B转入事务:B账户中+30元
  • B转入补偿事务:在执行过B转入事务的数据库中将A账户-30元

这里将一个全局事务拆分为两个短事务:A转出事务和B转入事务,成功执行事务顺序为:执行A转出事务 -> 执行B转入事务

如果A转出事务执行失败,那么整个事务执行流程应该是:A转出事务(失败) -> A转出补偿事务

如果B转入事务执行失败,那么整个事务执行流程应该是:A转出事务 -> B转入事务(失败) -> B转入补偿事务 -> A转出补偿事务

时序图如下,其中A转出事务为TransOut,B转入事务为TransIn:

file

补偿要考虑的情况

在短事务执行过程中,会有三种情况:1. 执行成功 2. 执行失败 3. 还在执行中,无法判断成功或失败,在事务补偿中,这三种情况都需要去考虑。

DTM提供了子事务屏障技术,自动处理上述三种情况,开发人员只需要编写好针对1的补偿操作情况即可,相关工作大幅简化,详细原理,参见下面的异常章节。

失败的分支是否需要补偿?

dtm 常被问到的一个问题是,TransIn返回失败,那么这个时候是否还需要调用TransIn的补偿操作?DTM 的做法是,统一进行一次调用,这种的设计考虑点如下:

  • XA, TCC 等事务模式是必须要的,SAGA 为了保持简单和统一,设计为总是调用补偿
  • DTM 支持单服务多数据源,可能出现数据源1成功,数据源2失败,这种情况下,需要确保补偿被调用,数据源1的补偿被执行
  • DTM 提供的子事务屏障,自动处理了补偿操作中的各种情况,用户只需要执行与正向操作完全相反的补偿即可

异常

偶发失败

在偶发的网络抖动、机器宕机、进程Crash的情况下,会偶发请求失败的场景,解决方法就是重试。

DTM中应该支持幂等的接口都支持幂等,所以在DTM中重试是安全的。

故障宕机

DTM在重试方面做了指数退避算法,如果遇见了故障宕机情况,那么指数退避可以避免大量请求不断发往故障应用,避免雪崩。

网络乱序

分布式系统中,网络延时是难以避免的,所以会发生一些乱序的情况,例如转账的例子中,可能发生服务器先收到撤销转账的请求,再收到转账请求。这类的问题是分布式事务中的一个重点难点问题,详情参考:异常与子事务屏障

二阶段消息

假设有三个微服务:本地应用A、微服务B、协调者C。

二阶段消息主要有三个流程:Prepare、Submit和QueryPrepared。

  • 本地应用A会发起Prepare请求给协调者C,预留事务资源和QueryPrepared接口。之后本地应用A开启并执行事务,协调者什么也不做。
  • 本地应用A执行完事务后,向协调者C发起Submit请求。协调者C收到请求后,将事务同步到微服务B。
  • 如果本地应用A超过一段时间未发起Submit,协调者C就会调用QueryPrepared接口。如果返回事务执行成功,则同步事务到微服务B。否则事务失败。

回查原理

在回查时,本地应用A的事务状态会有三种情况:执行中、事务执行成功、事务执行失败。

回查(QueryPrepared)原理:本地应用A在事务执行时会在数据库插入一条唯一主键gid(全局事务id)、原因为committed的数据。在回查的时候,会在数据库insert ignore一条主键为gid、原因为rollback的数据(由于insert带X锁,如果事务还在执行,sql会被堵塞,知道上一条事务结束才会被执行)。最后在查询数据库主键为gid的数据,查看事务执行结果。

为什么要在查询前insert?

如果事务在执行中,我们直接查询主键为gid的数据是查不到的,同样,如果事务发送回滚的话,查询gid也是查不到的。

如果只select,一般业界的做法是:重复轮询直到查出结果,如果超过两分钟还查不到数据,就认为事务回滚了。

但是如果机器出现P(Process Pause)情况,协调者认为事务回滚了,可是事务在P恢复时成功提交了,这又变成了悬挂问题。同时,长事务等情况的出现会导致轮询请求造成服务器不必要的压力。

易用性

采用新架构处理一致性问题,仅需要:
定义好本地业务逻辑,指定下一步处理的服务即可 定义QueryPrepared处理服务,复制粘贴例子代码即可。

TCC

TCC与XA类似,只不过TCC的阶段实在业务层上执行,XA阶段在数据库层上执行。在设计上,TCC主要用于处理一致性要求较高、需要较多灵活性的短事务。

TCC的事务操作是客户端编排的。

TCC是Try、Confirm、Cancel三个词语的缩写,是TCC事务过程中的三个阶段:

  • Try:预留必须的业务资源,进行业务的一致性检查操作,尝试执行。
  • Confirm:如果所有的try都成功了,执行业务,不做任何业务检查,只使用到try阶段预留的业务资源。
  • Cancel:如果try执行失败了,执行补偿操作。即释放try预留的业务资源。

由于TCC实在业务层面上执行的分布式事务,这三个阶段的业务逻辑都是自定义的,这使得TCC变得更佳灵活,开发者主要保证业务逻辑符合对应阶段的要求即可。

时序图如下:

file

失败回滚

如果任意try失败了,TCC会将全局事务中的所有子事务回滚。由于DTM的子事务屏障,开发者无需考虑回滚遇到的情况,只需要编写好回滚业务代码,执行回滚操作即可。

更好的一致性

由于TCC中有prepare阶段,因此操作更佳灵活,可以更好的保障一致性。下面还是以银行转账A转B30为例子。

由于SAGA只有一个提交,进行A余额扣除30的操作是真实扣除的。假如在进行B转账操作时失败,虽然会触发失败回滚,但是回滚期间A的余额确实扣除了30,知道回滚结束后A的余额扣除的30才得到返回。

使用TCC事务,可以在数据库中增加一个冻结余额字段:

  • 在准备阶段(Prepare):检查A的余额是否不少于30,检查完成后在冻结余额中增加30。
  • 在提交阶段(Confirm):A的冻结余额中减少30,同时余额减少30。
  • 在补偿阶段(Cancle):A的冻结余额减少30。

通过增加一个冻结字段,使得转账业务的一致性得以保证,在转账中不会出现转账失败,A的余额又被扣除的情况。

只适合短事务

由于TCC事务实在应用层上进行的,且编排是由客户端编排的。一旦发送进程崩溃等情况,会导致编排内容丢失,这种情况只能回滚(对比SAGA,同样的情况SAGA可以重试,因此SAGA适合长事务)。

DTM

DTM中的分布式事务

DTM中的ACID

  • 原子性:严格遵守原子性
  • 一致性:事务完成后的一致性严格遵循;事务中的一致性可适当放宽
  • 隔离性:严格遵守事务间不互相影响,事务运行时的可见性可以适当安全放宽
  • 持久性:严格遵守持久性

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ACK 云原生 AI 套件:云原生 AI 工程化落地最优路径

作者:胡玉瑜(稚柳) 前言 在过去几年中,人工智能技术取得了突飞猛进的发展,涵盖了机器学习、深度学习和神经网络等关键技术的重大突破,这使得人工智能在各个领域都得到广泛应用,对各行各业产生了深远的影响。 特别值…

pycharm安装汉化包失败解决方法

在pycharm -setting-plugins-搜索“Chinese”进入此界面: 点击install,在安装时出现:Plugin "Chinese (Simplified) Language Pack / 中文语言包" was not installed: Invalid filename returned by a server 解决方法&#xff1a…

从零开始学习 Java:简单易懂的入门指南之线程同步(三十五)

线程同步 1.线程同步1.1卖票【应用】1.2卖票案例的问题1.3同步代码块解决数据安全问题【应用】1.4同步方法解决数据安全问题【应用】1.5Lock锁【应用】1.6死锁 2.生产者消费者2.1生产者和消费者模式概述【应用】2.2生产者和消费者案例【应用】2.3生产者和消费者案例优化【应用】…

产品经理进阶:如何写商业计划书?

目录 简介 确定目标 确定目标市场 竞争分析 CSDN学院 作者简介 简介 很多时候,我们缺乏的并不是创意。 因为任何人都可能会萌发出一个好的创意。 但是,将想法变成可行的业务就完全是另一码事了。 你可能会认为你自己已经做好充分准备&#xff0…

Android studio安装详细教程

Android studio安装详细教程 文章目录 Android studio安装详细教程一、下载Android studio二、安装Android Studio三、启动Android Studio 一、下载Android studio Android studio安装的前提是必须保证安装了jdk1.8版本以上 1、打开android studio的官网:Download…

[网鼎杯 2018]Comment git泄露 / 恢复 二次注入 .DS_Store bash_history文件查看

首先我们看到账号密码有提示了 我们bp爆破一下 我首先对数字爆破 因为全字符的话太多了 爆出来了哦 所以账号密码也出来了 zhangwei zhangwei666 没有什么用啊 扫一下吧 有git git泄露 那泄露看看 真有 <?php include "mysql.php"; session_start(); if(…

selenium打开火狐浏览器

项目上需求为&#xff1a;甲方OA 系统是IE系统&#xff0c;需要从IE系统点个按钮打开火狐浏览器单点登录跳转到我们的系统 前期解决方案为&#xff1a;打开浏览器就行了&#xff0c;然后就用的是打开本地浏览器&#xff0c;但是由于B/S架构&#xff0c;有别人远程访问我的ip来…

WPF中的多重绑定

MultiBinding 将会给后端传回一个数组, 其顺序为绑定的顺序. 例如: <DataGridMargin"10"AutoGenerateColumns"False"ItemsSource"{Binding Stu}"><DataGrid.Columns><DataGridTextColumn Binding"{Binding Id}" Header…

伦敦银单位转换很简单

伦敦银源自于英国伦敦的电子化的白银投资方式&#xff0c;高杠杆和高收益的它的基本属性&#xff0c;但有别于国内大家所熟悉的投资品种&#xff0c;伦敦银在交易过程中有很多不一样的地方&#xff0c;需要大家地去留意。 比如伦敦银的计价单位是盎司&#xff0c;而且具体来说…

数据报表的种类

根据报表使用频率不同&#xff0c;目的不同&#xff0c;使用群体不同&#xff0c;细化程度不同等情况&#xff0c;一般数据报表可以分为日常报表和临时报表&#xff0c;日常报表又分为管理报表和专题分析报表。 1. 日常报表 日常报表通常是指使用频率较高&#xff08;一般取3…

亚马逊频繁扫号下的跨境电商,跨境电商卖家应该何去何从?

相信各位同行都知道&#xff0c;自2021年起&#xff0c;亚马逊的扫号活动就从未间断&#xff0c;直到如今2023年的亚马逊&#xff0c;仍然是隔2周-几个月就有大规模的审核扫号&#xff0c;大批卖家店铺被封&#xff0c;亚马逊卖家人人自危&#xff0c;面对时间间隔短频率高的扫…

微软 AR 眼镜新专利:包含热拔插电池

近日&#xff0c;微软在增强现实&#xff08;AR&#xff09;领域进行深入的研究&#xff0c;并申请了一项有关于“热插拔电池”的专利。该专利于2023年10月5日发布&#xff0c;描述了一款采用模块化设计的AR眼镜&#xff0c;其热插拔电池放置在镜腿部分&#xff0c;可以直接替代…

SyntaxError: invalid character ‘:‘ (U+FF1A)问题解决

问题&#xff1a; SyntaxError: invalid character &#xff1a; (UFF1A) 原因及解决方法&#xff1a; 冒号输入的格式不对&#xff0c;冒号的输入为中文&#xff0c;改成英文即可。

好用的Java工具类库—— Hutool

目录 一、简介 1、介绍 2、Hutool名称的由来 3、Hutool如何改变我们的coding方式 4、包含组件&#xff08;核心&#xff09; 5、官方文档 二、安装与使用 1、引入 import方式 exclude方式 2、安装(POM) 三、使用 1、DateUtil 2、StrUtil 3、NumberUtil 4、MapU…

打造类ChatGPT服务,本地部署大语言模型(LLM),如何远程访问?

ChatGPT的成功&#xff0c;让越来越多的人开始关注大语言模型&#xff08;LLM&#xff09;。如果拥有了属于自己的大语言模型&#xff0c;就可以对其进行一些专属优化。例如&#xff1a;打造属于自己的AI助理&#xff0c;或是满足企业自身的业务及信息安全需求。 所以&#xff…

centos 7 lamp owncloud

OwnCloud是一款开源的云存储软件&#xff0c;基于PHP的自建网盘。基本上是私人使用&#xff0c;没有用户注册功能&#xff0c;但是有用户添加功能&#xff0c;你可以无限制地添加用户&#xff0c;OwnCloud支持多个平台&#xff08;windows&#xff0c;MAC&#xff0c;Android&a…

如何使用自动化工具编写测试用例?

在快速变化的软件开发领域&#xff0c;保证应用程序的可靠性和质量至关重要。随着应用程序复杂性和规模的不断增加&#xff0c;仅手动测试无法满足行业需求。 这就是测试自动化发挥作用的地方&#xff0c;它使软件测试人员能够提高效率、增加测试覆盖率并自信地交付高质量的产品…

电动车租赁小程序开发方案详解php

电动车租赁小程序开发功能有哪些&#xff1f; 1.地图找车 进入小程序后&#xff0c;在地图上显示门店位置&#xff0c;点击位置可查看门店信息。进入门店后可以看到车辆列表&#xff0c;车辆里详细的介绍的车辆名称、图片、车辆介绍、租赁价格、押金等信息。 2.租赁/购车 电…

第五篇Android--EditText详解

EditText 字面意思可以编辑的文本。在Android中就是用来接收用户输入的输入框。 1.基本用法 <EditTextandroid:id"id/id_phone_edit"android:layout_width"match_parent"android:layout_height"48dp"android:background"android:color/…

Stable Diffusion 动画SD-Animatediff V2

AI不仅可以生成令人惊叹的图片,还能给这些图片注入生命,让它们动起来。 这就是AnimateDiff要做的事情,一个神奇的工具,能将静态的AI生成图像转换成动画。 本次介绍基于SD如何实现这个神奇的方法。 文章目录 插件安装使用方法参数调整文生动图/视频Controlnet方法SD API方…