分布式-事务

概述

什么事务分布式事务

就是一次大的操作由不同的小操作组成,这些小的操作分布在不同的服务器上,且属于不同的应用,分布式事务需要保证这些小操作要么全部成功,要么全部失败。本质上来说,分布式事务就是为了保证不同数据库的数据一致性。

分布式事务的产生的原因

数据库分库分表

当数据库单表一年产生的数据超过1000W,那么就要考虑分库分表,具体分库分表的原理在此不做解释,以后有空详细说,简单的说就是原来的一个数据库变成了多个数据库。这时候,如果一个操作既访问01库,又访问02库,而且要保证数据的一致性,那么就要用到分布式事务。

应用SOA化

所谓的SOA化,就是业务的服务化。比如原来单机支撑了整个电商网站,现在对整个网站进行拆解,分离出了订单中心、用户中心、库存中心。对于订单中心,有专门的数据库存储订单信息,用户中心也有专门的数据库存储用户信息,库存中心也会有专门的数据库存储库存信息。这时候如果要同时对订单和库存进行操作,那么就会涉及到订单数据库和库存数据库,为了保证数据一致性,就需要用到分布式事务。

以上两种情况表象不同,但是本质相同,都是因为要操作的数据库变多了!

数据库事务(单机事务)

概念理论

数据库事务大家应该都很熟悉了吧,什么数据库的特性ACID,事务隔离级别什么的,下面说下acid特性,事务的隔离级别在我之前的一篇中已经说到。

ACID

原子性(A)

所谓的原子性就是说,在整个事务中的所有操作,要么全部完成,要么全部不做,没有中间状态。

一致性(C)

事务的执行必须保证系统的一致性,就拿转账为例,A有500元,B有300元,如果在一个事务里A成功转给B50元,那么不管并发多少,不管发生什么,只要事务执行成功了,那么最后A账户一定是450元,B账户一定是350元。

隔离性(I)

所谓的隔离性就是说,事务与事务之间不会互相影响,一个事务的中间状态不会被其他事务感知。

持久性(D)

所谓的持久性,就是说一单事务完成了,那么事务对数据所做的变更就完全保存在了数据库中,即使发生停电,系统宕机也是如此。

分布式事务

概念理论

在单机情况下事务很容易满足,如果一个逻辑工作单元执行的一系列操作跨越了多台机器如何处理,多台机器相互之间又怎么知道对方成功了还是失败了。解决分布式事务的关键就是必须有一种方法能够知道事务在任何地方所做的任何动作,提交或者回滚的决定必须产生统一的结果。

如果再追求集群的ACID会导致我们的系统变得很差,这时我们就需要引入一个新的理论原则来适应这种集群的情况,就是 CAP 原则或者叫CAP定理,那么CAP定理指的是什么呢?

CAP定理

CAP定理是由加州大学伯克利分校Eric Brewer教授提出来的,他指出WEB服务无法同时满足一下3个属性:

  • 一致性(Consistency) : 客户端知道一系列的操作都会同时发生(生效)
  • 可用性(Availability) : 每个操作都必须以可预期的响应结束
  • 分区容错性(Partition tolerance) : 即使出现单个组件无法可用,操作依然可以完成

具体地讲在分布式系统中,在任何数据库设计中,一个Web应用至多只能同时支持上面的两个属性。显然,任何横向扩展策略都要依赖于数据分区。因此,设计人员必须在一致性与可用性之间做出选择。

在分布式系统中,我们往往追求的是可用性,它的重要程序比一致性要高,那么如何实现高可用性呢? 前人已经给我们提出来了另外一个理论,就是BASE理论,它是用来对CAP定理进行进一步扩充的,下面我们说下这个理论

BASE 理论

BASE理论指的是:

Basically Available(基本可用)

Soft state(软状态)

Eventually consistent(最终一致性)

BASE理论是对CAP中的一致性和可用性进行一个权衡的结果,理论的核心思想就是:我们无法做到强一致,但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性(Eventual consistency)。也就是告诉我们:可以通过放弃系统在每个时刻的强一致性来换取系统的可扩展性。

分布式事务解决方案

一、基于XA协议的两阶段提交

XA是一个分布式事务协议,由Tuxedo提出。XA中大致分为两部分:事务管理器和本地资源管理器。其中本地资源管理器往往由数据库实现,比如Oracle、DB2这些商业数据库都实现了XA接口,而事务管理器作为全局的调度者,负责各个本地资源的提交和回滚。

XA 是一个两阶段提交协议,该协议分为以下两个阶段:

第一阶段:事务协调器要求每个涉及到事务的数据库预提交(precommit)此操作,并反映是否可以提交

第二阶段:事务协调器要求每个数据库提交数据。

两阶段提交(Two Phase Commit, 2PC), 基于XA协议来的。

MySQL从5.5版本开始支持,SQL Server 2005 开始支持,Oracle 7 开始支持。

2PC

一、说明

第一阶段:称为准备(prepare)阶段。事务协调者向各个服务应用发送prepare请求,服务应用在得到请求后做预处理操作,预处理可能是做预检查,也可能是把请求临时存储,可以理解为是一种试探性地提交。下面是一般的步骤:

a.事务协调者会问所有的参与者服务,是否可以提交操作。

b.各个参与者开始事务执行的准备工作:如资源上锁,预留资源,写回滚/重试的log。

c.参与者响应协调者,如果事务准备工作成功,则回应“可以提交”,否则回应拒绝提交。

第二阶段:称为提交(commit)/回滚(rollback)阶段。是指事务真正提交或者回滚的阶段。如果事务协调者发现事务参与者有一个在prepare阶段出现失败,则会要求所有的参与者进行回滚。如果协调者发现所有的参与者都prepare操作都是成功,那么他将向所有的参与者发出提交请求,这时所有参与者才会正式提交。由此保证了要求全部提交成功,要么全部失败。下面是具体步骤:

a.如果所有的参与者都回应“可以提交”,那么协调者向所有参与者发送“正式提交”的命令。参与者完成正式提交,并释放所有资源,然后回应“完成”,协调者收集各个服务的“完成”回应后结束事务。

b.如果有一个参与者回应“拒绝提交”,那么协调者向所有的参与者发送“回滚操作”,并释放所有的资源,然后回应“回滚完成”,协调者收集各个服务应用的“回滚”返回后,取消整体的分布式事务。

二、问题缺点

二阶段提交协议解决的是分布式系统/微服务架构中数据强一致性的问题,其原理简单,但缺点也是存在,主要缺点如下:

a.单点问题:协调者在整个二阶段中的作用非常重要,一旦部署协调者组件服务的节点出现不可用宕机情况,那么会影响整个分布式系统的正常运行。

b.同步阻塞:二阶段提交执行过程中,所有服务参与者需要服从协调者的统一调度,期间处于阻塞状态,会一定程度上影响整个系统的效率。

c、数据不一致:当第二阶段开始提交,一台接收到了commit,另外一台由于网络问题,或者宕机,同样会出现数据不一致的情况

3PC

主要分三个阶段

第一阶段协调者询问参与者是否可以执行事务,参与者就分析自身是否能够成功执行事务操作,可以则返回yes,否则no

第二阶段参与者收到后则开始执行事务操作,执行成功后反馈yes给协调者反之no

第三阶段协调者根据参与者的反馈选择发起abort或者commit命令

改进点

增加了超时机制

第二阶段,如果协调者超时没有接受到参与者的反馈,则自动认为失败,发送abort命令

第三阶段,如果参与者超时没有接受到协调者的反馈,则自动认为成功开始提交事务(基于概率)

2PC与3PC的区别

相对于2PC,3PC主要解决的单点故障问题,并减少阻塞,因为一旦参与者无法及时收到来自协调者的信息之后,他会默认执行commit。而不会一直持有事务资源并处于阻塞状态。但是这种机制也会导致数据一致性问题,因为,由于网络原因,协调者发送的abort响应没有及时被参与者接收到,那么参与者在等待超时之后执行了commit操作。这样就和其他接到abort命令并执行回滚的参与者之间存在数据不一致的情况。

二、基于消息

这类事务机制将分布式事务分成多个本地事务,这里称之为主事务与从事务。首先主事务本地先行提交,然后通过消息通知从事务,从事务从消息中获取信息进行本地提交。可以看出这是一种异步事务机制、只能保证最终一致性;但可用性非常高,不会因为故障而发生阻塞。另外,主事务已经先行提交,如果因为从事务无法提交,要回滚主事务还是比较麻烦,所以这种模式只适用于理论上大概率等成功的业务情况,即从事务的提交失败可能是由于故障,而不大可能是逻辑错误。

基于异步消息的事务机制主要有两种方式:本地消息表与事务消息。二者的区别在于:怎么保证主事务的提交与消息发送这两个操作的原子性。

本地消息表(异步确保)

本地消息表这种实现方式应该是业界使用最多的,其核心思想是将分布式事务拆分成本地事务进行处理,这种思路是来源于ebay。我们可以从下面的流程图中看出其中的一些细节:

基本思路就是:

消息生产方,需要额外建一个消息表,并记录消息发送状态。消息表和业务数据要在一个事务里提交,也就是说他们要在一个数据库里面。然后消息会经过MQ发送到消息的消费方。如果消息发送失败,会进行重试发送。

消息消费方,需要处理这个消息,并完成自己的业务逻辑。此时如果本地事务处理成功,表明已经处理成功了,如果处理失败,那么就会重试执行。如果是业务上面的失败,可以给生产方发送一个业务补偿消息,通知生产方进行回滚等操作。

生产方和消费方定时扫描本地消息表,把还没处理完成的消息或者失败的消息再发送一遍。如果有靠谱的自动对账补账逻辑,这种方案还是非常实用的。

这种方案遵循BASE理论,采用的是最终一致性,笔者认为是这几种方案里面比较适合实际业务场景的,即不会出现像2PC那样复杂的实现(当调用链很长的时候,2PC的可用性是非常低的),也不会像TCC那样可能出现确认或者回滚不了的情况。

优点: 一种非常经典的实现,避免了分布式事务,实现了最终一致性。

缺点: 消息表会耦合到业务系统中,如果没有封装好的解决方案,会有很多杂活需要处理。

事务消息

事务消息依赖于支持“事务消息”的消息队列,其基本思想是 利用消息中间间实施两阶段提交,将本地事务和发消息放在了一个分布式事务里,保证要么本地操作成功成功并且对外发消息成功,要么两者都失败。流程如下: 

相比本地消息表的方式,事务消息由消息中间件保证本地事务与消息的原子性,不依赖于本地数据库存储消息。有些MQ支持事务消息,有些不支持;

对于不支持:

1)支付宝在扣款事务提交之前,向实时消息服务请求发送消息,实时消息服务只记录消息数据,而不真正发送。

2)当支付宝扣款事务被提交成功后,向实时消息服务确认发送。

3)当支付宝扣款事务提交失败回滚后,向实时消息服务取消发送。

4)对于那些未确认的消息或者取消的消息,需要有一个消息状态确认系统定时去支付宝系统查询这个消息的状态并进行更新。为什么需要这一步骤,举个例子:假设在第2步支付宝扣款事务被成功提交后,系统挂了,此时消息状态并未被更新为“确认发送”,从而导致消息不能被发送。

目前阿里的 RocketMQ 支持消息事务,其思路大致为:

第一阶段Prepared消息,会拿到消息的地址。

第二阶段执行本地事务,第三阶段通过第一阶段拿到的地址去访问消息,并修改状态。

也就是说在业务方法内要想消息队列提交两次请求,一次发送消息和一次确认消息。如果确认消息发送失败了RocketMQ会定期扫描消息集群中的事务消息,这时候发现了Prepared消息,它会向消息发送者确认,所以生产方需要实现一个check接口,RocketMQ会根据发送端设置的策略来决定是回滚还是继续发送确认消息。这样就保证了消息发送与本地事务同时成功或同时失败。

不管是本地消息表还是事务消息,都需要保证从事务执行且仅仅执行一次,exact once。如果失败,需要重试,但也不可能无限次的重试,当从事务最终失败的情况下,需要通知主业务回滚吗?但是此时,主事务已经提交,因此只能通过补偿,实现逻辑上的回滚,而当前时间点距主事务的提交已经有一定时间,回滚也可能失败。因此,最好是保证从事务逻辑上不会失败,万一失败,记录log并报警,人工介入。

原文地址:https://www.cnblogs.com/xckxue/p/8686570.html

时间: 2024-10-26 22:58:06

分布式-事务的相关文章

XA分布式事务

XA分布式事务 XA XA协议由Tuxedo首先提出的,并交给X/Open组织,作为资源管理器(数据库)与事务管理器的接口标准.目前,Oracle.Informix.DB2和Sybase等各大数据库厂家都提供对XA的支持.XA协议采用两阶段提交方式来管理分布式事务.XA接口提供资源管理器与事务管理器之间进行通信的标准接口.XA协议包括两套函数,以xa_开头的及以ax_开头的 简介编辑 取决于上下文, XA 有多种意思. 我们常见的数据库连接交易中的 XA 是指由 X/Open 组织提出的分布式交

浅谈分布式事务

前言应用场景 事务必须满足传统事务的特性,即原子性,一致性,分离性和持久性.但是分布式事务处理过程中, 某些场地比如在电商系统中,当有用户下单后,除了在订单表插入一条记录外,对应商品表的这个商品数量必须减1吧,怎么保证? 在搜索广告系统中,当用户点击某广告后,除了在点击事件表中增加一条记录外,还得去商家账户表中找到这个商家并扣除广告费吧,怎么保证? 一 本地事务以用户A转账用户B为例,假设有 用户A账户表:A(id,userId,amount) 用户B账户表:B(id,userId,amount

聊聊分布式事务

聊聊分布式事务 2017-04-15 数据库开发 (点击上方公众号,可快速关注) 作者:员海滨 nickid.cn/2017/04/分布式事务/ 如有好文章投稿,请点击 → 这里了解详情 分布式事务场景如何设计系统架构及解决数据一致性问题,个人理解最终方案把握以下原则就可以了,那就是:大事务=小事务(原子事务)+异步(消息通知),解决分布式事务的最好办法其实就是不考虑分布式事务,将一个大的业务进行拆分,整个大的业务流程,转化成若干个小的业务流程,然后通过设计补偿流程从而考虑最终一致性. 什么是事

使用事件和消息队列实现分布式事务(转+补充)

虽然本文并非笔者原创,但是我们在非强依赖的事务中原理上也是采用这种方式处理的,不过因为没有仔细去总结,最近在整理和总结时看到了,故转载并做部分根据我们实际情况的完善和补充. 不同于单一架构应用(Monolith), 分布式环境下, 进行事务操作将变得困难, 因为分布式环境通常会有多个数据源, 只用本地数据库事务难以保证多个数据源数据的一致性. 这种情况下, 可以使用两阶段或者三阶段提交协议来完成分布式事务.但是使用这种方式一般来说性能较差, 因为事务管理器需要在多个数据源之间进行多次等待. 有一

java分布式事务

原文地址:http://blog.csdn.net/moonpure/article/details/52779794 在本系列先前的文章中,我们主要讲解了JDBC对本地事务的处理,本篇文章将讲到一个分布式事务的例子. 请通过以下方式下载github源代码: git clone https://github.com/davenkin/jta-atomikos-hibernate-activemq.git 本地事务和分布式事务的区别在于:本地事务只用于处理单一数据源事务(比如单个数据库),分布式事

分布式事务 解决方案

事务的概念来源于业务过程.在许多情况下我们都希望能够确保在一个过程中执行的所有操作是完全成功的.在集中式系统中,事务被广泛用于服务器端和数据库系统,控制数据的操作.随着分布式计算的发展,事务在分布式计算领域中也得到了广泛的应用,但是分布式系统架构中,分布式事务问题是一个绕不过去的挑战.而微服务架构的流行,让分布式事问题日益突出! 下面我们以电商购物支付流程中,在各大参与者系统中可能会遇到分布式事务问题的场景进行详细的分析! 如上图所示,假设三大参与平台(电商平台.支付平台.银行)的系统都做了分布

关于分布式事务、两阶段提交、一阶段提交、Best Efforts 1PC模式和事务补偿机制的研究[转]

1.XA XA是由X/Open组织提出的分布式事务的规范.XA规范主要定义了(全局)事务管理器(Transaction Manager)和(局部)资源管理器(Resource Manager)之间的接口.XA接口是双向的系统接口,在事务管理器(Transaction Manager)以及一个或多个资源管理器(Resource Manager)之间形成通信桥梁.XA之所以需要引入事务管理器是因为,在分布式系统中,从理论上讲(参考Fischer等的论文),两台机器理论上无法达到一致的状态,需要引入一

本地事务和分布式事务工作实践 【转】

一:从事务的历史说起 知已知彼,百战不败.想了解事务,我们从事务的历史说起. 在Windows平台上,事务的概念最开始出现在关系型数据库中,但是随着.net平台的发展,事务包括的的范围也越来越宽,先一睹为快, 在关系型数据库中的事务是通过begin transaction,rollback transaction, commit 等关键字来实现事务的. BEGIN TRANSACTION  UPDATE [dbo].[T_ACCOUNT] SET BALANCE = BALANCE + @amo

【故障处理】分布式事务ORA-01591错误解决

[故障处理]分布式事务ORA-01591错误解决 1  BLOG文档结构图       2  前言部分 2.1  导读和注意事项 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道的知识,~O(∩_∩)O~: ① 分布式事务的简单概念         ② ORA-01591错误解决   Tips: ① 本文在ITpub(http://blog.itpub.net/26736162).博客园(http://www.cnblogs.com/lhrbest)和微信公众号(x

对分布式事务、消息队列的重新认识

本质上问题可以抽象为:当一个表数据更新后,怎么保证另一个表的数据也必须要更新成功.若两张表在同一个数据库实例中,则使用本地事务就好了.否则可以采用分布式事务,或者消息队列. 前阵子从支付宝转账1万块钱到余额宝,这是日常生活的一件普通小事,但作为互联网研发人员的职业病,我就思考支付宝扣除1万之后,如果系统挂掉怎么办,这时余额宝账户并没有增加1万,数据就会出现不一致状况了. 上述场景在各个类型的系统中都能找到相似影子,比如在电商系统中,当有用户下单后,除了在订单表插入一条记录外,对应商品表的这个商品