【事务】——分布式事务

前言


去银行存钱,存进去了,余额没增加是个怎样的心情?如果是去取钱,余额没减又是一个怎样的心情?为什么会出现这种情况?怎样才能避免呢?有了事务就能解决上述问题。

事务定义


事务提供一种机制将一个活动涉及的所有操作纳入到一个不可分割的执行单元,组成事务的所有操作只有在所有操作均能正常执行的情况下方能提交,只要其中任一操作执行失败,都将导致整个事务的回滚。简单地说,事务提供一种“要么什么都不做,要么做全套(All or Nothing)”机制。

数据库本地事务


数据库的四大特性:ACID
A:原子性(Atomicity)
C:一致性(Consistency)
I:隔离性(Isolation)
D:持久性(Durability)
事务的ACID是通过InnoDB日志和锁来保证。事务的隔离性是通过数据库锁的机制实现的,持久性通过redo log(重做日志)来实现,原子性和一致性通过Undo log来实现。

分布式事务

一、什么是分布式事务:

分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。以上是百度百科的解释,简单的说,就是一次大的操作由不同的小操作组成,这些小的操作分布在不同的服务器上,且属于不同的应用,分布式事务需要保证这些小操作要么全部成功,要么全部失败。本质上来说,分布式事务就是为了保证不同数据库的数据一致性。

场景:

当下互联网发展如火如荼,绝大部分公司都进行了数据库拆分和服务化(SOA)。在这种情况下,完成某一个业务功能可能需要横跨多个服务,操作多个数据库,这就涉及到到了分布式事务。
跨库事务:
跨库事务指的是,一个应用某个功能需要操作多个库,不同的库中存储不同的业务数据。
【事务】——分布式事务
分库分表:
通常一个库数据量比较大或者预期未来的数据量比较大,都会进行水平拆分,也就是分库分表。如下图,将数据库B拆分成了2个库:
【事务】——分布式事务
服务化(SOA):
当业务逻辑越来越复杂,设计的库越来越多,挑战会不断加大,将应用拆分成不同的独立服务,简化业务逻辑。拆分后独立服务之间通过RPC框架来进行远程调用,实现彼此通信。
【事务】——分布式事务
Service A完成某个功能需要直接操作数据库,同时需要调用Service B和Service C,而Service B又同时操作了2个数据库,Service C也操作了一个库。需要保证这些跨服务的对多个数据库的操作要不都成功,要不都失败,实际上这可能是最典型的分布式事务场景。

二、分布式事务基础:

分布式事务随着互联网高速发展营运而生,这是的之前的数据库ACID四大特性难以满足分布式事务,这是产生了一些新的理论:

CAP定理:

CAP理论告诉我们,一个分布式系统不能同时满足一致性,可用性和分区容错性这三个基本需求,最多只能同时满足其中两项。
➢一致性:
在分布式环境中,一致性是指数据在多个副本之间是否能够保持一致特性。在一致性的需求下,当一个系统在数据一直的状态下执行更新操作后,应该保证系统的数据仍然处于一致的状态。
可用性:
可用性实质系统提供的服务必须一直处于可用的状态,对于用户的每一个操作请求总是能够在有限的时间内返回结果。
有限的时间内:是指对于用户的一个操作请求,系统必须能够在指定的时间(即相应时间)内返回对应的处理结果,如果超过了这个时间范围,那么系统就被认为是不可能的。
返回结果:是可用性的另一个指标,它要求系统在完成对用户请求的处理后,返回一个正常的响应结果。正常的响应结果通常能够明确地反映出对请求的处理结果,即成功或失败,而不是一个让用户迷惑的返回结果。
分区容错性:
分布式系统在遇到任何网络分区故障的时候,仍然需要能够保证对外提供满足一致性和可用性的服务,除非是整个网络环境都发生了故障。
CAP定理示意图:
【事务】——分布式事务

BASE理论:

BASE理论是Basically Available(基本可用)、Soft state(软状态)和Eventually consistent(最终一致性)三个短语的简写,BASE是对CAP中一致性和可用性权衡的结果,其核心思想是及时无法做到强一致性,但每个应用都可以根据自身的业务特点,采用适当的方式使系统达到最终一致性。
基本可用:
基本可用是指分布式系统在出现不可预知故障的时候,允许损失部分可用性。这不等价于系统不可用。

  • 响应时间上的损失: 正常情况下,一个在线搜索引擎需要在0.5秒内返回给用户相应的查询结果,但由于出现故障,比如系统部分机房发生断点或断网故障,查询结果的享用时间增加到1~2秒。
  • 功能上的损失: 正常情况下,在一个电子商务网站上进行购物,消费者几乎能够顺利的完成每一笔订单,但是在一些节日大促购物高峰的时候,由于消费者的购物行为激增,为了保护系统的稳定性,部分消费者可能会被引导到一个降级页面。

弱状态:
弱状态也成为软状态,和硬状态相对,是指允许系统中的数据存在中间状态,并认为该中间状态的存在不会影响系统的整体可用性,即允许系统在不同节点的数据副本之间进行数据同步的过程存在延迟。
最终一致性:
最终一致性强调的是系统所有的数据副本,在经过一段时间的同步后,最终能够达到一个一致的状态。因此,最终一致性的本质是需要系统保证最终数据能能够达到一致,而不需要实时保证系统数据的强一致性。
最终一致性五类主要变种:
因果一致性,读己之所写,会话一致性,单调读一致性,单调写一致性

三、XA规范

X/Open 组织(即现在的 Open Group )定义了分布式事务处理模型。 X/Open DTP 模型( 1994 )包括应用程序( AP )、事务管理器( TM )、资源管理器( RM )、通信资源管理器( CRM )四部分。一般,常见的事务管理器( TM )是交易中间件,常见的资源管理器( RM )是数据库,常见的通信资源管理器( CRM )是消息中间件。
二阶提交协议和三阶提交协议就是根据这一思想衍生出来的。可以说二阶段提交其实就是实现XA分布式事务的关键。确切地说:两阶段提交主要保证了分布式事务的原子性:即所有结点要么全做要么全不做。

四、一致性协议:

在对一个分布式系统进行架构设计的过程中,往往会在系统的可用性和数据一致性之间进行反复的权衡,于是就产生一系列的一致性协议。最著名的是二阶段提交协议、三阶段提交协议。

➢2PC:

2PC是Two-Phase Commit 的缩写,即二阶段提交。是将事务的提交过程分成了两个阶段来进行处理。
执行流程:
阶段一:提交事务请求
1、事务询问
协调者向所有的参与者发送事务内容,询问是否可以执行事务提交操作,并开始等待个参与者的响应。
2、执行事务
各参与者节点执行事务操作,并将Undo和Redo信息记入事务日志中。
3、各参与者向协调者返回事务询问的响应
如果参与者成功执行了事务操作,那么就反馈给协调者Yes响应,表示事务可以执行;如果参与者没有成功执行事务,就反馈给协调者No响应,表示事务不可以执行。
阶段二:执行事务提交
在阶段二中,协调者会根据各参与者的反馈情况来决定最终是否可以进行事务提交操作,正常情况下,包含以下两种可能。
Case1:执行事务提交
记入协调者从所有参与者阔的的反馈都是Yes相应,那么就会执行事务提交。
1、发送提交请求
协调者想所有参与者节点发出Commit请求。
2、事务提交
参与者接收到Commit请求后,会正式执行事务提交操作,并在完成提交之后释放在整个事务执行期间占用的事务资源。
3、反馈事务提交结果
参与者在完成事务提交之后,向协调者发送Ack消息。
4、完成事务
协调者接收到所有参与者反馈的Ack消息后,完成事务。
【事务】——分布式事务
Case:中断事务
假如任何一个参与者向协调者反馈了No响应,或者在等待超时之后,协调者尚无法接收到所有参与者的反馈相应,那么就会终端事务。
1、发送回滚请求
协调者向所有参与者节点发送Rollback请求。
2、事务回滚
参与者接收到Rollback请求后,会利用其在阶段一种记录的Undo信息来执行事务回滚操作,并在完成回滚之后释放在整个事务执行期间占用的资源。
3、反馈事务回滚结果
参与者在完成事务回滚之后,想协调者发送Ack消息。
4、中断事务
协调者接收到所有参与者反馈的Ack消息后,完成事务中断。
【事务】——分布式事务
二阶段提交将一个事务的处理过程分为了投票和执行两个阶段,其核心是对每个事务都采用先尝试后提交的处理方式,因此也可以将二阶段提交看作一个强一致性的算法。
优缺点:
优点:原理简单,是实现方便
缺点:同步阻塞,单点问题,脑裂,太过保守

3PC

在二阶段提交协议的基础上进行了改进,提出了三阶段提交协议。
3PC是Three-Phase Cpmmit的缩写,即三阶段提交,是2PC的改进版,形成了由CanCommit、PreCommit和doCommit三个阶段组成的事务处理协议。
第一阶段:CanCommit阶段
【事务】——分布式事务
1.事务询问
协调者向参与者发送CanCommit请求。询问是否可以执行事务提交操作。然后开始等待参与者的响应。
2.响应反馈
参与者接到CanCommit请求之后,正常情况下,如果其自身认为可以顺利执行事务,则返回Yes响应,并进入预备状态。否则反馈No。
第二阶段:PreCommit阶段
协调者根据参与者的反应情况来决定是否可以进行事务的PreCommit操作。根据响应情况,有以下两种可能。
假如协调者从所有的参与者获得的反馈都是Yes响应,那么就会执行事务的预执行。
Case1:执行事务预提交
1.发送预提交请求
协调者向参与者发送PreCommit请求,并进入Prepared阶段。
2.事务预提交
参与者接收到PreCommit请求后,会执行事务操作,并将undo和redo信息记录到事务日志中。
3.响应反馈
如果参与者成功的执行了事务操作,则返回ACK响应,同时开始等待最终指令。

假如有任何一个参与者向协调者发送了No响应,或者等待超时之后,协调者都没有接到参与者的响应,那么就执行事务的中断。
Case2:中断事务
1.发送中断请求
协调者向所有参与者发送abort请求。
2.中断事务
参与者收到来自协调者的abort请求之后(或超时之后,仍未收到协调者的请求),执行事务的中断。
第三阶段:doCommit阶段
该阶段进行真正的事务提交,也可以分为以下两种情况。
Case 1:执行提交
1.发送提交请求
协调接收到参与者发送的ACK响应,那么他将从预提交状态进入到提交状态。并向所有参与者发送doCommit请求。
2.事务提交
参与者接收到doCommit请求之后,执行正式的事务提交。并在完成事务提交之后释放所有事务资源。
3.响应反馈
事务提交完之后,向协调者发送Ack响应。
4.完成事务
协调者接收到所有参与者的ack响应之后,完成事务。
Case 2:中断事务
协调者没有接收到参与者发送的ACK响应(可能是接受者发送的不是ACK响应,也可能响应超时),那么就会执行中断事务。
1.发送中断请求
协调者向所有参与者发送abort请求
2.事务回滚
参与者接收到abort请求之后,利用其在阶段二记录的undo信息来执行事务的回滚操作,并在完成回滚之后释放所有的事务资源。
3.反馈结果
参与者完成事务回滚之后,向协调者发送ACK消息
4.中断事务
协调者接收到参与者反馈的ACK消息之后,执行事务的中断。

优缺点:
优点:降低了参与者阻塞范围,并且能够在出现单点故障后继续达成一致。
缺点:在去除阻塞的同时引入了新问题,即参与者接收到preCommit消息后,如果网络出现分区,此时协调者所在的节点和参与者无法进行正常网络通信,这时,参与者依然会进行事务提交,这必然导致数据不一致。