您的位置 首页 > 数码极客

关系型数据如何达成强一致性

前言

使用Spring Cloud构建微服务应用绕不过的一个难点就是跨服务的业务操作的数据一致性问题,今天小编就和大家一起来研究一下。

ACID理论

在单体架构的时代,业务系统通常是使用关系型数据库来做存储的,如果一个业务操作需要对同一个数据库进行多次操作,其数据的一致性由数据库的事务来保证,这依赖的就是关系型数据库的ACID理论。

ACID是Atomic、Consistency、 Isolation、 Durability 四个单词的缩写,它们的含义如下:

  1. Atomic (原子性):事务的原子性要求事务必须是一个原子的操作系列。一个事务中包含的各个操作在一次执行过程中, 要么全部执行,要么全部不执行,任何一个操作失败,整个事务回滚;只有该事务中所有操作都执行成功,整个事务才提交。
  2. Consistency (一致性): 事务的一致性要求事务提交之后,原有的约束及规则不被破坏,如果一个事务产生了违反已有约束及规则的数据,那么它们需要被回退到事务开始时的状态。这里的一致性,对数据库来说就是不违反相关约束,比如唯一约束、外键约束等;对于应用系统的业务层面来说,则是事务提交之后相关数据满足业务规则的要求。
  3. Isolation (隔离性):事务的隔离性要求并发中的事务是相互隔离的,即不同的事务操作相同的数据时,每个事务是独立相互不干扰的,具体而言有读未提交、读已提交、可重复读、串行化4种事务隔离级别。如果没有事务隔离的话,那么就可能会有更新丢失、脏读、不可重复读、幻读的异常。
  4. Durability (持久性):事务的持久性要求事务一旦提交,则它对数据的变更应该是持久的,即当事务提交数据持久化之后,如果系统崩溃,那么重启之后需要能够看到该事务修改之后的数据。

X/Open DTP模型

如果一个业务操作涉及对多个数据源进行操作,那么使用原来单一数据库的事务(本地事务)来控制就会不能满足(全局事务)数据的一致性要求。为此x/Open组织定义了DTP(Distributed Transaction Processing)模型(如下图所示),来规范全局事务处理。

DTP模型组件视图

如上图所示,它定义了几个组件,分别如下:

  • AP (Application Program, 应用程序):即需要使用分布式事务的应用服务。
  • RM (Resource Manager, 资源管理器):比如数据库或文件系统,提供对共享资源的访问,保障资源的ACID特性。
  • TM (Transaction Manager,事务管理器):主要是给事务分配唯一标识,负责事务的启动、提交及回滚,保障全局事务的原子性。
  • CRMs ( Communication Resource Managers,通信资源管理器):负责控制分布式应用在TMdomain(一组使用同一个TM的实例集合)之内或跨TMdomain之间的通信,该通信使用的是OSI TP ( Open Systems Interconnection Distributed Transaction Processing)服务。早期规范里并没有提出CRM组件的概念,这是在后面版本的规范中提出的。
  • 通信协议:即由通信资源管理器支持,在分布式应用使用的通信协议。

XA接口与JTA

XA接口是x/OpenDTP在2PC的基础上给事务管理器TM与资源管理器RM之间通信定义的接口。在Java领域,J2EE (Java Enterprise Edition)定义了JTA (Java Transaction API)规范,它遵循X/Open XA接口,是高级版本的API规范。另外还有JTS ( Java Transaction Service)规范,其定义了更底层的实现事务管理器TM的相关接口,其中包括支持高级别的JTA接口以及标准的CORBAObjectTransactionService到Java的映射。JTS对于Java的XA事务规范,类似于JMS (Java Message Service)对于Java的消息中间件规范。JTA与JTS的关系如下图所示。

JTA与JTS

JTA主要定义如下几个类:

  • javax.。
  • javax.。
  • javax.。
  • javax.。
  • javax.。
  • javax.。
  • javax.。
  • javax..TxType。
  • javax.。

JDBC与XA相关的几个类如下:

  • javax.。
  • javax.sq1. XAConnection。

CAP与BASE定理

ACID与CAP它们中都有一个C,不过其一致性的含义不太一样: ACID的C主要关注的是数据在跨节点操作情况下的操作原子性,而CAP的C关注的是同一份数据在多个副本之间同步的一致性。

BASE是Basically Available (基本可用)、Soft state (软状态)、Eventually consistent (最终一致性)这四个单词的缩写。在单体架构往分布式架构迁移时,数据一致性要做到满足ACID特性往往比较困难,于是BASE定理就提出在一些非严格要求强一致的应用场景下面,应用可以根据情况采取适当的措施来达到最终一致性, 其宗旨是通过牺牲强-致来获取可用性。

使用XA事务来实现分布式事务,其可用性就比较差,于是业界提出了TCC及SAGA等解决方案,其思想跟BASE定理类似,通过打破ACID特性中的-个或几个来提升分布式事务的可用性。

Java 事务编程接口JTA

满足J2EE规范的容器支持了JTA规范,在纯J2SE领域,Spring Boot官方文档推荐了atomikos、bitronix、 narayana这三个组件。这里分别对它们简单介绍一下:

  • atomikos:希腊语的含义就是原子性,以这个词作为分布式事务组件的名称,用于暗指其可靠的事务管理能力。关于atomikos有开源的版本( TransactionsEssentials),也有增强的收费版( Extreme Transactions)。
  • bitronix:BTM ( Bitronix Transaction Manager)是一款简单但是完整实现了JTA1.1 规范的事务管理器。
  • arayana:它是jboss提供的一款分布式事务管理器,有基于J2EE容器的版本,也有standalone的版本,目前实现了JTA1.2版本的规范。

分布式事务TCC模式

1、定义

  • Tentative Operation:为了在多个实体之间达成一致,要求一个实体必须能够接受另一个实体对请求执行的不确定性,比如,在发出执行操作请求之后又发出取消该操作的请求。这类后续可能请求取消的操作,就称为Tentative Operation。
  • Confirmation:如果请求方认为Tentative Operation没问题,那么就可以发出Confirmation的执行请求,最终确定这个操作。
  • Cancellation:如果请求方决定撤回Tentative Operation,那么就发出Cancellation 的执行请求,取消这个操作。

当一个实体统一执行Tentative Operation的时候,就意味着它接受了这种不确定性,允许另外的实体通过发出Confirmation或者Cancellation 请求,来降低这种不确定性,最终完成这个Tentative Operation。

Gregor Hohpe在其维护的www.en网站中,将Pat Helland提出的Tentative Operations、Confirmation 和Cancellation 模型概括为Tentative Operation模式,然后提出与之类似的TCC (Try-Confirm-Cancel)事务模型,其状态图如下所示。

TCC状态图

TCC事务模型总共有Initial、Reserved、 Final 三个状态:

  • Initial 状态:是最初始的状态,接到Try请求时变成Reserved状态。
  • Reserved 状态:接收Confirm请求时变成Final状态,如果接收Cancel请求或者是等待超时则退回到Initial状态。
  • Final状态:TCC事务成功状态。

2、TCC与2PC

与2PC不同,TCC的模式把原来2PC的prepare操作从事务管理中剥离出来,规范为try操作,并且变为Reserved状态。同理也将撤销prepare的操作规范为cancel操作,并且变为Initial状态。通过这样的规范,使得TCC模式可以更好地适应SOA架构的分布式事务场景,并规范原来黑盒的操作,委托给各个业务场景去实现,将业务服务纳入整个分布式事务的处理当中。这样做的好处就是把原来的黑盒操作暴露出来,在出现不一致的场景(比如timeout的时候出现了confirm 请求,或者confirm的时候出现失败)可以通过手工等方式介人。

3、TCC与ACID

TCC模式不满足Isolation 的特性,即TCC是采用预留资源的方式来做try以及cancel操作的,那么在达到final状态之前,其他事务如果读取处于中间状态的资源的时候,读到的是“脏”数据。

另外TCC要求confirm、cancel 操作必须是幂等的,因为实际场景会因为网络等其他问题导致这些操作被重试,因此TCC实现的是最终-致性的分布式事务。

分布式事SAGA模式

1、定义

1987年普林斯顿大学的Hector Garcaa-Molrna与Kenneth Salem发表了一篇名为《SAGAS》的论文,提出了SAGA的事务模式。它涉及一个概念——LLT ( Long Lived Transaction)。 LLT指的是持有数据库资源相对较长的长活事务。如果一个LLT可以被拆解为一序列可以跟其他事务错开执行(interleaved with)的子事务,而且里面的每个子事务保持自身ACID特性,要么可以成功提交,要么可以通过补偿事务( compensating transaction)来进行恢复,从而达到最终一致性,那么这个LLT就可称为SAGA。

2015年CaitieMcCaffrey及Kyle Kingsbury将SAGAS模式应用到分布式系统当中,提出了Distributed Sagas模式。该模式定义了SEC (Saga Execution Coordinator)以及TEC (Transaction Execution Coordinator)。

对于整个SEC,启动的时候为Sagastart,中断的时候为Sagaabort,执行完成的时候为Saga done。从图24-5可以看出,每次操作之前都会先log一下,另外还维护了一个变量i,用来控制SAGA的子事务是否执行完或者补偿完,然后结束整个流程。

Distributed Saga对正常请求及补偿请求有如下几点要求:

  • 正常请求以及补偿请求都必须是幂等的。
  • 补偿请求是commutative的,commutative在这里的意思是:如果一个正常请求在补偿请求之后到达,那么正常请求不应该被执行。
  • 正常请求可以被中断(触发补偿请求),但是补偿请求必须执行完成,没有中断操作。

SEC的执行逻辑

2、SAGA与2PC

与2PC相比,SAGA与TCC通过牺牲ACID的部分特性来提升分布式事务的可用性。另外SAGA及TCC可以理解为是服务层面的事务模式,将分布式事务的控制由数据库事务层提升到服务层。

3、SAGA与TCC

SAGA与TCC最显著的区别在于TCC采用的是预留资源的方式,其状态里有个Reserved状态;而SAGA则没有这个预留资源的动作,事务直接提交,然后采取的是补偿事务的方式来进行撤回。与2PC相比,2PC采用事务prepare以及rollback动作,整个都在一个大事务中,而SAGA是将这些大事务拆分为一个个本地事务。

4、SAGA与ACID

SAGA模式不满足Isolation的特性,因为其将LLt划分为一个个本地事务,一旦本地事务提交,在整个SAGA执行完毕之前,中间如果有其他事务也访问到了共享资源,则会读到“未完成”的事务的数据。与TCC类似,SAGA 不满足C特性,SAGA实现的是最终一致性,但是拆分出来的一个个本地事务则满足ACID特性。

总结

本文我们首先简述了单体架构数据库ACID的特性、XA事务模型以及BASE定理,然后梳理了JTA、TCC及SAGA三种分布式事务的模式,相信大家对分布式事务处理也有了一个基本的认识。

感觉文章能帮到自己的朋友,请帮小编点个关注,后续小编会再带来更丰富的学习内容更新,希望大家喜欢!!!

责任编辑: 鲁达

1.内容基于多重复合算法人工智能语言模型创作,旨在以深度学习研究为目的传播信息知识,内容观点与本网站无关,反馈举报请
2.仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证;
3.本站属于非营利性站点无毒无广告,请读者放心使用!

“关系型数据如何达成强一致性”边界阅读