1.0 分布式事务概述 2018-02-05 02:05:26 32,685 16
1、事务简介
事务 (Transaction) 是拜访并可能更新数据库中各种数据项的一个程序执行单元(unit)。在关系数据库中,一个事务由一组 SQL 语句组成。事务应该具备 4 个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为 ACID 个性。原子性(atomicity):个事务是一个不可分割的工作单位,事务中包含的诸操作要么都做,要么都不做。一致性(consistency):事务必须是使数据库从一个一致性状态变到另一个一致性状态,事务的中间状态不能被察看到的。隔离性(isolation):一个事务的执行不能被其余事务烦扰。即一个事务外部的操作及应用的数据对并发的其余事务是隔离的,并发执行的各个事务之间不能相互烦扰。隔离性又分为四个级别:读未提交(read uncommitted)、读已提交(read committed,解决脏读)、可反复读(repeatable read,解决虚读)、串行化(serializable,解决幻读)。持久性(durability):持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的扭转就应该是永久性的。接下来的其余操作或故障不应该对其有任何影响。任何事务机制在实现时,都应该思考事务的 ACID 个性,包含:本地事务、分布式事务,及时不能都很好的满足,也要思考反对到什么水平。
2 本地事务
大多数场景下,咱们的利用都只须要操作繁多的数据库,这种状况下的事务称之为本地事务(Local Transaction)。本地事务的 ACID 个性是数据库间接提供反对。本地事务利用架构如下所示:
在 JDBC 编程中,咱们通过 java.sql.Connection 对象来开启、敞开或者提交事务。代码如下所示:
Connection conn = … // 获取数据库连贯
conn.setAutoCommit(false); // 开启事务
try{
//… 执行增删改查 sql
conn.commit(); // 提交事务
}catch (Exception e) {
conn.rollback();// 事务回滚
}finally{
conn.close();// 敞开链接
}
此外,很多 java 利用都整合了 spring,并应用其申明式事务管理性能来实现事务性能。个别应用的步骤如下:
1、配置事务管理器。spring 提供了一个 PlatformTransactionManager 接口,其有 2 个重要的实现类:DataSourceTransactionManager:用于反对本地事务,事实上,其外部也是通过操作 java.sql.Connection 来开启、提交和回滚事务。JtaTransactionManager:用于反对分布式事务,其实现了 JTA 标准,应用 XA 协定进行两阶段提交。须要留神的是,这只是一个代理,咱们须要为其提供一个 JTA provider,个别是 Java EE 容器提供的事务协调器(Java EE server's transaction coordinator),也能够不依赖容器,配置一个本地的 JTA provider。2、在须要开启的事务的 bean 的办法上增加 @Transitional 注解
能够看到,spring 除了反对本地事务,也反对分布式事务,上面咱们先对分布式事务的典型利用场景进行介绍。
3 分布式事务典型场景
当下互联网倒退热火朝天,绝大部分公司都进行了数据库拆分和服务化(SOA)。在这种状况下,实现某一个业务性能可能须要横跨多个服务,操作多个数据库。这就波及到到了分布式事务,用须要操作的资源位于多个资源服务器上,而利用须要保障对于多个资源服务器的数据的操作,要么全副胜利,要么全副失败。实质上来说,分布式事务就是为了保障不同资源服务器的数据一致性。
典型的分布式事务场景:
1、跨库事务
跨库事务指的是,一个利用某个性能须要操作多个库,不同的库中存储不同的业务数据。笔者见过一个绝对比较复杂的业务,一个业务中同时操作了 9 个库。下图演示了一个服务同时操作 2 个库的状况:
2、分库分表
通常一个库数据量比拟大或者预期将来的数据量比拟大,都会进行程度拆分,也就是分库分表。如下图,将数据库 B 拆分成了 2 个库:
对于分库分表的状况,个别开发人员都会应用一些数据库中间件来升高 sql 操作的复杂性。如,对于 sql:insert into user(id,name) values (1,"tianshouzhi"),(2,"wangxiaoxiao")。这条 sql 是操作单库的语法,单库状况下,能够保障事务的一致性。然而因为当初进行了分库分表,开发人员心愿将 1 号记录插入分库 1,2 号记录插入分库 2。所以数据库中间件要将其改写为 2 条 sql,别离插入两个不同的分库,此时要保障两个库要不都胜利,要不都失败,因而基本上所有的数据库中间件都面临着分布式事务的问题。
3、服务化(SOA)
微服务架构是目前一个比拟一个比拟火的概念。例如下面笔者提到的一个案例,某个利用同时操作了 9 个库,这样的利用业务逻辑必然非常复杂,对于开发人员是极大的挑战,应该拆分成不同的独立服务,以简化业务逻辑。拆分后,独立服务之间通过 RPC 框架来进行近程调用,实现彼此的通信。下图演示了一个 3 个服务之间彼此调用的架构:
Service A 实现某个性能须要间接操作数据库,同时须要调用 Service B 和 Service C,而 Service B 又同时操作了 2 个数据库,Service C 也操作了一个库。须要保障这些跨服务的对多个数据库的操作要不都胜利,要不都失败,实际上这可能是最典型的分布式事务场景。小结:上述探讨的分布式事务场景中,无一例外的都间接或者间接的操作了多个数据库。如何保障事务的 ACID 个性,对于分布式事务实现计划而言,是十分大的挑战。同时,分布式事务实现计划还必须要思考性能的问题,如果为了严格保障 ACID 个性,导致性能重大降落,那么对于一些要求疾速响应的业务,是无奈承受的。
4 X/Open DTP 模型与 XA 标准
X/Open,即当初的 open group,是一个独立的组织,次要负责制订各种行业技术标准。官网地址:http://www.opengroup.org/。X/Open 组织次要由各大出名公司或者厂商进行反对,这些组织不光遵循 X /Open 组织定义的行业技术标准,也参加到规范的制订。下图展现了 open group 目前次要成员(官网截图):
能够看到,中国人的自豪,华为,赫然在列!!!此处应该有掌声。
就分布式事务处理 (Distributed Transaction Processing, 简称 DTP) 而言,X/Open 次要提供了以下参考文档:
DTP 参考模型:<<Distributed Transaction Processing: Reference Model>>
DTP XA 标准:<< Distributed Transaction Processing: The XA Specification>>
4.1 DTP 模型
1、模型元素
在 <<Distributed Transaction Processing: Reference Model>> 第 3 版中,规定了形成 DTP 模型的 5 个根本元素:
应用程序(Application Program,简称 AP):用于定义事务边界(即定义事务的开始和完结),并且在事务边界内对资源进行操作。
资源管理器(Resource Manager,简称 RM):如数据库、文件系统等,并提供拜访资源的形式。
事务管理器(Transaction Manager,简称 TM):负责调配事务惟一标识,监控事务的执行进度,并负责事务的提交、回滚等。
通信资源管理器 (Communication Resource Manager,简称 CRM):管制一个 TM 域(TM domain) 内或者跨 TM 域的分布式应用之间的通信。
通信协议(Communication Protocol,简称 CP):提供 CRM 提供的分布式应用节点之间的底层通信服务。
其中因为通信资源管理器 (Communication Resource Manager) 和通信协议 (Communication Protocol) 是一对好基友,从 Communication Protocol 的简称 CP 上就可以看进去,两个元素的关系不个别,因而有的文章在介绍 DTP 模型元素时,只提到了通信资源管理器....
2、模型实例(Instance of the Model)
一个 DTP 模型实例,至多有 3 个组成部分:AP、RMs、TM。如下所示:
这张图相似于咱们之前提到的跨库事务的概念,即单个利用须要操作多个库。在这里就是一个 AP 须要操作多个 RM 上的资源。AP 通过 TM 来申明一个全局事务,而后操作不同的 RM 上的资源,最初告诉 TM 来提交或者回滚全局事务。特地的,如果分布式事务须要跨多个利用,相似于咱们后面的提到的分布式事务场景中的服务化,那么每个模型实例中,还须要额定的退出一个通信资源管理器 CRM。下图中演示了 2 个模型实例,如何通过 CRM 来进行通信:
CRM 作为多个模型实例之间通信的桥梁,次要作用如下:
根本的通信能力:从这个角度,能够将 CRM 类比为 RPC 框架,模型实例之间通过 RPC 调用实现彼此的通信。这一点体现在 AP、CRM 之间的连线。
事务流传能力:与传统 RPC 框架不同的是,CRM 底层采纳 OSI TP(Open Systems Interconnection — Distributed Transaction Processing)通信服务,因而 CRM 具备事务流传能力。这一点体现 TM、CRM 之间的连线。
2、事务管理器作用域(TM domain)
一个 TM domain 中由一个或者多个模型实例组成,这些模型实例应用的都是同一个 TM,然而操作的 RMs 各不相同,由 TM 来对立协调这些模型实例独特参加造成的全局事务(global transaction)。
下图展现了一个由四个模型实例组成的 TM Domain,这四个模型实例应用的都是同一个事务管理器 TM1。
TM domain 只是列出了最终参加到一个全局事务中,有哪些模型实例,并不关怀这些模型实例之间的关系。这就好比,有一个班级,咱们只是想晓得这个班级中每位同学的名字,然而并不是关怀谁是班长、谁是学习委员等。不过显然的,当一个 TM domain 中存在多个模型实例时,模型实例彼此之间存在肯定的层级调用关系。这就是全局事务的树形构造。
3 全局事务树形构造(Global Transaction Tree Structure)
当一个 TM domain 中,存在多个模型实例时,会造成一种树形条用关系,如下图所示:
其中:
发动分布式事务的模型实例称之为 root 节点,或者称之为事务的发起者,其余的模型实例能够统称为事务的参与者。事务发起者负责开启整个全局事务,事务参与者各自负责执行本人的事务分支。而从模型实例之间的互相调用关系来说,调用方称之为上游节点(Superior Node),被调用方称之为上游节点(Subordinate Node)。
小结:通过对 DTP 模型的介绍,咱们能够看进去,之前提到的分布式事务的几种典型场景实际上在 DTP 模型中都蕴含了,甚至比咱们思考的还简单。DTP 模型从最早提出到当初曾经有靠近 30 年,到现在仍然实用,不得不拜服模型的设计者是很有远见的。
4.2 XA 标准
在 DTP 本地模型实例中,由 AP、RMs 和 TM 组成,不须要其余元素。AP、RM 和 TM 之间,彼此都须要进行交互,如下图所示:
这张图中 (1) 示意 AP-RM 的交互接口,(2)示意 AP-TM 的交互接口,(3)示意 RM-TM 的交互接口。对于这张图,XA 标准有以下形容:
The subject of this X/Open specification is interface (3) in the diagram above, the XA interface by which TMs and RMs interact.
For more details on this model and diagram, including detailed definitions of each component, see the referenced DTP guide.
也就是说 XA 标准的最次要的作用是,就是定义了 RM-TM 的交互接口,下图更加清晰了演示了 XA 标准在 DTP 模型中发挥作用的地位,从下图中能够看进去,XA 仅仅呈现在 RM 和 TM 的连线上。
XA 标准除了定义的 RM-TM 交互的接口 (XA Interface) 之外,还对两阶段提交协定进行了优化。一些读者可能会误认为两阶段提交协定是在 XA 标准中提出来的。事实上:两阶段协定 (two-phase commit) 是在 OSI TP 规范中提出的;在 DTP 参考模型 (<<Distributed Transaction Processing: Reference Model>>) 中,指定了全局事务的提交要应用 two-phase commit 协定;而 XA 标准 (<< Distributed Transaction Processing: The XA Specification>>) 只是定义了两阶段提交协定中须要应用到的接口,也就是上述提到的 RM-TM 交互的接口,因为两阶段提交过程中的参与方,只有 TM 和 RMs。参见 <<Distributed Transaction Processing: Reference Model>> 第 3 版 2.1 节,原文如下:
Commitment Protocol
A commitment protocol is the synchronisation that occurs at transaction completion. The X/Open DTP Model follows the two-phase commit with presumed rollback1 protocol defined in the referenced OSI TP standards. A description of the basic protocol is given in Section 3.4.3 on page 13. In certain cases, a global transaction may be completed heuristically. Heuristic transaction completion is described in Section 3.4.5 on page 14.
4.2.1 XA Interface
XA 标准中定义的 RM 和 TM 交互的接口如下图所示:
对于这些接口的具体解释,能够间接参考 XA 标准。前面在解说到 mysql 对 XA 事务的反对时,咱们也会应用到局部命令。
4.2.2 两阶段提交协定(2PC)
两阶段提交协定(Two Phase Commit)不是在 XA 标准中提出,然而 XA 标准对其进行了优化,因而对立放到这里进行解说。而从字面意思来了解,Two Phase Commit,就是将提交 (commit) 过程划分为 2 个阶段(Phase):
In Phase 1, the TM asks all RMs to prepare to commit (or prepare) transaction branches. This asks whether the RM can guarantee its ability to commit the transaction branch. An RM may have to query other entities internal to that RM.
If an RM can commit its work, it records stably the information it needs to do so, then replies affirmatively. A negative reply reports failure for any reason. After making a negative reply and rolling back its work, the RM can discard any knowledge it has of the transaction branch.
In Phase 2, the TM issues all RMs an actual request to commit or roll back the transaction branch, as the case may be. (Before issuing requests to commit, the TM stably records the fact that it decided to commit, as well as a list of all involved RMs.) All RMs commit or roll back changes to shared resources and then return status to the TM. The TM can then discard its knowledge of the global transaction.
阶段 1:
TM 告诉各个 RM 筹备提交它们的事务分支。如果 RM 判断本人进行的工作能够被提交,那就就对工作内容进行长久化,再给 TM 必定回答;要是产生了其余状况,那给 TM 的都是否定回答。在发送了否定回答并回滚了曾经的工作后,RM 就能够抛弃这个事务分支信息。以 mysql 数据库为例,在第一阶段,事务管理器向所有波及到的数据库服务器收回 prepare"筹备提交" 申请,数据库收到申请后执行数据批改和日志记录等解决,解决实现后只是把事务的状态改成 "能够提交", 而后把后果返回给事务管理器。
阶段 2
TM 依据阶段 1 各个 RM prepare 的后果,决定是提交还是回滚事务。如果所有的 RM 都 prepare 胜利,那么 TM 告诉所有的 RM 进行提交;如果有 RM prepare 失败的话,则 TM 告诉所有 RM 回滚本人的事务分支。以 mysql 数据库为例,如果第一阶段中所有数据库都 prepare 胜利,那么事务管理器向数据库服务器收回 "确认提交" 申请,数据库服务器把事务的 "能够提交" 状态改为 "提交实现" 状态,而后返回应答。如果在第一阶段内有任何一个数据库的操作产生了谬误,或者事务管理器收不到某个数据库的回应,则认为事务失败,回撤所有数据库的事务。数据库服务器收不到第二阶段的确认提交申请,也会把 "能够提交" 的事务回撤。
XA 标准对两阶段提交协定有 2 点优化:
Protocol Optimisations
• Read-only
An RM can respond to the TM’s prepare request by asserting that the RM was not asked to update shared resources in this transaction branch. This response concludes the RM’s involvement in the transaction; the Phase 2 dialogue between the TM and this RM does not occur. The TM need not stably record, in its list of participating RMs, an RM that asserts a read-only role in the global transaction.
However, if the RM returns the read-only optimisation before all work on the global transaction is prepared, global serialisability1 cannot be guaranteed. This is because the RM may release transaction context, such as read locks, before all application activity for that global transaction is finished.
- One-phase Commit
A TM can use one-phase commit if it knows that there is only one RM anywhere in the DTP system that is making changes to shared resources. In this optimisation, the TM makes its Phase 2 commit request without having made a Phase 1 prepare request. Since the RM decides the outcome of the transaction branch and forgets about the transaction branch before returning to the TM, there is no need for the TM to record stably these global transactions and, in some failure cases, the TM may not know the outcome.
只读断言
在 Phase 1 中,RM 能够断言“我这边不波及数据增删改”来回答 TM 的 prepare 申请,从而让这个 RM 脱离以后的全局事务,从而免去了 Phase 2。
这种优化产生在其余 RM 都实现 prepare 之前的话,应用了只读断言的 RM 早于 AP 其余动作(比如说这个 RM 返回那些只读数据给 AP)前,就开释了相干数据的上下文(比方读锁之类的),这时候其余全局事务或者本地事务就有机会去扭转这些数据,后果就是无奈保障整个零碎的可序列化个性——艰深点说那就会有脏读的危险。
一阶段提交
如果须要增删改的数据都在同一个 RM 上,TM 能够应用一阶段提交——跳过两阶段提交中的 Phase 1,间接执行 Phase 2。
这种优化的实质是跳过 Phase 1,RM 自行决定了事务分支的后果,并且在回答 TM 前就革除掉事务分支信息。对于这种优化的状况,TM 实际上也没有必要去牢靠的记录全局事务的信息,在一些异样的场景下,此时 TM 可能不晓得事务分支的执行后果。
4.2.3 两阶段提交协定 (2PC) 存在的问题
二阶段提交看起来的确可能提供原子性的操作,然而可怜的是,二阶段提交还是有几个毛病的:
1、同步阻塞问题。两阶段提交计划下全局事务的 ACID 个性,是依赖于 RM 的。例如 mysql5.7 官网文档对于对 XA 分布式事务的反对有以下介绍:
https://dev.mysql.com/doc/ref…
A global transaction involves several actions that are transactional in themselves, but that all must either complete successfully as a group, or all be rolled back as a group. In essence, this extends ACID properties“up a level”so that multiple ACID transactions can be executed in concert as components of a global operation that also has ACID properties. (As with nondistributed transactions, SERIALIZABLE may be preferred if your applications are sensitive to read phenomena. REPEATABLE READ may not be sufficient for distributed transactions.)
大抵含意是说,一个全局事务外部蕴含了多个独立的事务分支,这一组事务分支要不都胜利,要不都失败。各个事务分支的 ACID 个性独特形成了全局事务的 ACID 个性。也就是将单个事务分支的反对的 ACID 个性晋升一个档次 (up a level) 到分布式事务的领域。括号中的内容的意思是:即便在非散布事务中(即本地事务),如果对操作读很敏感,咱们也须要将事务隔离级别设置为 SERIALIZABLE。而对于分布式事务来说,更是如此,可反复读隔离级别不足以保障分布式事务一致性。也就是说,如果咱们应用 mysql 来反对 XA 分布式事务的话,那么最好将事务隔离级别设置为 SERIALIZABLE。地球人都晓得,SERIALIZABLE(串行化)是四个事务隔离级别中最高的一个级别,也是执行效率最低的一个级别。
2、单点故障。因为协调者的重要性,一旦协调者 TM 产生故障。参与者 RM 会始终阻塞上来。尤其在第二阶段,协调者产生故障,那么所有的参与者还都处于锁定事务资源的状态中,而无奈持续实现事务操作。(如果是协调者挂掉,能够从新选举一个协调者,然而无奈解决因为协调者宕机导致的参与者处于阻塞状态的问题)
3、数据不统一。在二阶段提交的阶段二中,当协调者向参与者发送 commit 申请之后,产生了部分网络异样或者在发送 commit 申请过程中协调者产生了故障,这回导致只有一部分参与者承受到了 commit 申请。而在这部分参与者接到 commit 申请之后就会执行 commit 操作。然而其余局部未接到 commit 申请的机器则无奈执行事务提交。于是整个分布式系统便呈现了数据不一致性的景象。
因为二阶段提交存在着诸如同步阻塞、单点问题等缺点,所以,研究者们在二阶段提交的根底上做了改良,提出了三阶段提交。
5 三阶段提交协定(Three-phase commit)
三阶段提交(3PC),是二阶段提交(2PC)的改良版本。参考维基百科:https://en.wikipedia.org/wiki/Three-phase_commit_protocol
与两阶段提交不同的是,三阶段提交有两个改变点。
1、引入超时机制。同时在协调者和参与者中都引入超时机制。2、在第一阶段和第二阶段中插入一个筹备阶段。保障了在最初提交阶段之前各参加节点的状态是统一的。也就是说,除了引入超时机制之外,3PC 把 2PC 的筹备阶段再次一分为二,这样三阶段提交就有 CanCommit、PreCommit、DoCommit 三个阶段。
CanCommit 阶段
3PC 的 CanCommit 阶段其实和 2PC 的筹备阶段很像。协调者向参与者发送 commit 申请,参与者如果能够提交就返回 Yes 响应,否则返回 No 响应。1. 事务询问 协调者向参与者发送 CanCommit 申请。询问是否能够执行事务提交操作。而后开始期待参与者的响应。2. 响应反馈 参与者接到 CanCommit 申请之后,失常状况下,如果其本身认为能够顺利执行事务,则返回 Yes 响应,并进入准备状态。否则反馈 No
PreCommit 阶段
协调者依据参与者的反馈状况来决定是否能够忘性事务的 PreCommit 操作。依据响应状况,有以下两种可能。如果协调者从所有的参与者取得的反馈都是 Yes 响应,那么就会执行事务的预执行。1. 发送预提交申请 协调者向参与者发送 PreCommit 申请,并进入 Prepared 阶段。2. 事务预提交 参与者接管到 PreCommit 申请后,会执行事务操作,并将 undo 和 redo 信息记录到事务日志中。3. 响应反馈 如果参与者胜利的执行了事务操作,则返回 ACK 响应,同时开始期待最终指令。
如果有任何一个参与者向协调者发送了 No 响应,或者期待超时之后,协调者都没有接到参与者的响应,那么就执行事务的中断。
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 音讯之后,执行事务的中断。在 doCommit 阶段,如果参与者无奈及时接管到来自协调者的 doCommit 或者 rebort 申请时,会在期待超时之后,会持续进行事务的提交。(其实这个应该是基于概率来决定的,当进入第三阶段时,阐明参与者在第二阶段曾经收到了 PreCommit 申请,那么协调者产生 PreCommit 申请的前提条件是他在第二阶段开始之前,收到所有参与者的 CanCommit 响应都是 Yes。(一旦参与者收到了 PreCommit,象征他晓得大家其实都批准批改了)所以,一句话概括就是,当进入第三阶段时,因为网络超时等起因,尽管参与者没有收到 commit 或者 abort 响应,然而他有理由置信:胜利提交的几率很大。)
小结:2PC 与 3PC 的区别
绝对于 2PC,3PC 次要解决的单点故障问题,并缩小阻塞,因为一旦参与者无奈及时收到来自协调者的信息之后,他会默认执行 commit。而不会始终持有事务资源并处于阻塞状态。然而这种机制也会导致数据一致性问题,因为,因为网络起因,协调者发送的 abort 响应没有及时被参与者接管到,那么参与者在期待超时之后执行了 commit 操作。这样就和其余接到 abort 命令并执行回滚的参与者之间存在数据不统一的状况。理解了 2PC 和 3PC 之后,咱们能够发现,无论是二阶段提交还是三阶段提交都无奈彻底解决分布式的一致性问题。Google Chubby 的作者 Mike Burrows 说过,there is only one consensus protocol, and that’s Paxos”– all other approaches are just broken versions of Paxos. 意即世上只有一种一致性算法,那就是 Paxos,所有其余一致性算法都是 Paxos 算法的不完整版。前面的文章会介绍这个公认为难于了解然而卓有成效的 Paxos 算法。
6 BASE 实践与柔性事务
6.1 经典的分布式系统实践 -CAP
2000 年 7 月,加州大学伯克利分校的 Eric Brewer 传授在 ACM PODC 会议上提出 CAP 猜测。Brewer 认为在设计一个大规模的分布式系统时会遇到三个个性:一致性(consistency)、可用性(Availability)、分区容错(partition-tolerance),而一个分布式系统最多只能满足其中的 2 项。2 年后,麻省理工学院的 Seth Gilbert 和 Nancy Lynch 从实践上证实了 CAP。之后,CAP 实践正式成为分布式计算畛域的公认定理。
- 一致性
一致性指“all nodes see the same data at the same time”,即更新操作胜利并返回客户端实现后,所有节点在同一时间的数据完全一致,不能存在中间状态。例如对于电商零碎用户下单操作,库存缩小、用户资金账户扣减、积分减少等操作必须在用户下单操作实现后必须是统一的。不能呈现相似于库存曾经缩小,而用户资金账户尚未扣减,积分也未减少的状况。如果呈现了这种状况,那么就认为是不统一的。
对于一致性,如果确实能像下面形容的那样时刻保障客户端看到的数据都是统一的,那么称之为强一致性。如果容许存在中间状态,只要求通过一段时间后,数据最终是统一的,则称之为最终一致性。此外,如果容许存在局部数据不统一,那么就称之为弱一致性。
- 可用性
可用性是指零碎提供的服务必须始终处于可用的状态,对于用户的每一个操作申请总是可能在无限的工夫内返回后果。“无限的工夫内”是指,对于用户的一个操作申请,零碎必须可能在指定的工夫内返回对应的处理结果,如果超过了这个工夫范畴,那么零碎就被认为是不可用的。试想,如果一个下单操作,为了保障分布式事务的一致性,须要 10 分钟能力解决完,那么用户显然是无法忍受的。“返回后果”是可用性的另一个十分重要的指标,它要求零碎在实现对用户申请的解决后,返回一个失常的响应后果,不管这个后果是胜利还是失败。
- 分区容错性
分布式系统在遇到任何网络分区故障的时候,依然须要可能保障对外提供满足一致性和可用性的服务,除非是整个网络环境都产生了故障。
小结:既然一个分布式系统无奈同时满足一致性、可用性、分区容错性三个特点,咱们就须要摈弃一个,须要明确的一点是,对于一个分布式系统而言,分区容错性是一个最根本的要求。因为既然是一个分布式系统,那么分布式系统中的组件必然须要被部署到不同的节点,否则也就无所谓分布式系统了。而对于分布式系统而言,网络问题又是一个必定会呈现的异常情况,因而分区容错性也就成为了一个分布式系统必然须要面对和解决的问题。因而零碎架构师往往须要把精力花在如何依据业务特点在 C(一致性)和 A(可用性)之间寻求均衡。而后面咱们提到的 X /Open XA 两阶段提交协定的分布式事务计划,强调的就是一致性;因为可用性较低,理论利用的并不多。而基于 BASE 实践的柔性事务,强调的是可用性,目前大行其道,大部分互联网公司采可能会优先采纳这种计划。
6.2 BASE 实践
eBay 的架构师 Dan Pritchett 源于对大规模分布式系统的实际总结,在 ACM 上发表文章提出 BASE 实践。文章链接:https://queue.acm.org/detail.cfm?id=1394128
BASE 实践是对 CAP 实践的延长,核心思想是即便无奈做到强一致性(Strong Consistency,CAP 的一致性就是强一致性),但利用能够采纳适宜的形式达到最终一致性(Eventual Consitency)。
BASE 是 Basically Available(根本可用)、Soft state(软状态)和 Eventually consistent(最终一致性)三个短语的缩写。
1. 根本可用(Basically Available)指分布式系统在呈现不可预知故障的时候,容许损失局部可用性。2. 软状态(Soft State)指容许零碎中的数据存在中间状态,并认为该中间状态的存在不会影响零碎的整体可用性。3. 最终统一(Eventual Consistency)强调的是所有的数据更新操作,在通过一段时间的同步之后,最终都可能达到一个统一的状态。因而,最终一致性的实质是须要零碎保障最终数据可能达到统一,而不须要实时保证系统数据的强一致性。BASE 实践面向的是大型高可用可扩大的分布式系统,和传统的事物 ACID 个性是相同的。它齐全不同于 ACID 的强一致性模型,而是通过就义强一致性来取得可用性,并容许数据在一段时间内是不统一的,但最终达到统一状态。但同时,在理论的分布式场景中,不同业务单元和组件对数据一致性的要求是不同的,因而在具体的分布式系统架构设计过程中,ACID 个性和 BASE 实践往往又会联合在一起。
6.3 典型的柔性事务计划
最大致力告诉(非可靠消息、定期校对)可靠消息最终一致性(异步确保型)TCC(两阶段型、弥补型)
起源:http://www.tianshouzhi.com/ap…
欢送关注公众号【码农开花】一起学习成长
我会始终分享 Java 干货,也会分享收费的学习材料课程和面试宝典
回复:【计算机】【设计模式】【面试】有惊喜哦