文章目录
一、事务概述
1、事务概念
事务是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。
2、事务的作用
简而言之,事务是为解决数据安全操作提出的,事务控制实际上就是控制数据的安全访问。
事务的产生,其实是为了当应用程序访问数据库的时候,让我们开发人员不需要去考虑各种各样的潜在错误和并发问题。当我们使用事务时,要么提交,要么回滚,我们不需要去考虑网络异常,服务器宕机,同时更改一个数据怎么处理?因此事务本质上是为了应用层服务的,而不是伴随着数据库系统天生就有的。
一个烂了的栗子:
银行转帐业务,账户A要将自己账户上的1000元转到B账户下面,A账户余额首先要减去1000元,然后B账户要增加1000元。假如在中间网络出现了问题,A账户减去1000元已经结束,B因为网络中断而操作失败,那么整个业务失败,必须做出控制,要求A账户转帐业务撤销。这才能保证业务的正确性,完成这个操走就需要事务,将A账户资金减少和B账户资金增加放到同一个事务里,要么全部执行成功,要么全部撤销,这样就保证了数据的安全性。
3、事务的特性(ACID)
数据库事务 transanction 正确执行的四个基本要素:原子性(Atomicity)、一致性(Correspondence)、隔离性(Isolation)、持久性(Durability),称之为ACID特性。
- 原子性(Atomicity):事务是数据库的逻辑工作单位,而且是必须是原子工作单位,对于其数据修改,要么全部执行,要么全部不执行。
- 一致性(Consistency):事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。因此当数据库只包含成功事务提交的结果时,就说数据库处于一致性状态。如果数据库系统运行中发生故障,有些事务尚未完成就被迫中断,这些未完成事务对数据库所做的修改有一部分已写入物理数据库,这时数据库就处于一种不正确的状态,或者说是不一致的状态。
- 隔离性(Isolation):一个事务的执行不能被其他事务所影响。
- 持久性(Durability):一个事务一旦提交,事物的操作便永久性的保存在DB中。接下来的其它操作或故障不应该对其执行结果有任何影响。
任何事务机制在实现时,都应该考虑事务的ACID特性,包括:本地事务、分布式事务,即使不能都很好的满足,也要考虑支持到什么程度。
另外,文本着重对事务的一致性进行讨论。在ACID中,AID都是数据库的特征,也就是依赖数据库来具体实现,而唯独这个C,实际上它依赖于应用层,也就是依赖于开发者,开发者要做的事情就是通过数据库对事务AID的支持,来保证C。其中AID是后端,C是目的。这里的C是指系统从一个正确的状态,迁移到另一个正确的状态.什么叫正确的状态呢?就是当前的状态满足预定的约束就叫做正确的状态.
再举一个例子
把事务比作一个保镖,我们提到事务就会说ACID,而我们提到保镖会说强壮,功夫好,威猛,这里的强壮,功夫好,威猛都是保镖自己的特征。而当我雇佣一个保镖时,希望的是通过保镖的这些特性,来保证我的安全,这个安全属性是属于我的。
同理,在程序中使用事务,是想通过事务的AID特性,来保证数据在程序中的一致性。
4、本地事务
大多数场景下,我们的应用都只需要操作单一的数据库,这种情况下的事务称之为本地事务(Local Transaction
)也可称之为单机事务。
二、分布式事务
随着业务规模和场景越趋于复杂与庞大。很多公司都进行了数据库拆分和服务化(SOA)。在这种情况下,完成某一个业务功能可能需要横跨多个服务,操作多个数据库。这就涉及到到了分布式事务,其中需要操作的资源位于多个资源服务器上,而应用需要保证对于多个资源服务器的数据的操作,要么全部成功,要么全部失败。本质上来说,分布式事务就是为了保证不同资源服务器的数据一致性。
1、场景模拟
下图是分布式系统中的一个业务场景。其中每个微服务维护其私有的数据库。在此业务逻辑中,前端发送一个创建Order的请求。调用Order Server创建订单,Order Server需调用Inventory Server减库存。
在这里,Order Server的创建订单功能和Inventory Server的减库存功能分别是一个单独的事务。涉及到如何保证分布式系统两个事务一致性的问题。假定网络因素,导致调用Inventory Server超时,订单创建了,而库存却没有减少,这便导致了整个业务失去了该有的一致性。
而这个问题就是分布式事务需要解决的问题,单应用下单数据源的一致性依靠单机事务来保证,而分布式系统下的多数据源的一致性则靠分布式事务来解决。
为了简化问题,这里举的例子比较简单,实际的业务场景肯定复杂许多。如何保证事务的ACID特性,对于分布式事务实现方案而言,是非常大的挑战。同时,根据业务规模的大小,分布式事务实现方案还必须要考虑性能的问题,如果为了严格保证ACID特性,导致性能严重下降,那么对于一些要求快速响应的业务,也是无法接受的。
三、分布式事务的解决方案
1、X/Open DTP模型与XA规范
X/Open,即现在的open group,是一个独立的组织,主要负责制定各种行业技术标准。官网地址:http://www.opengroup.org/。X/Open组织主要由各大知名公司或者厂商进行支持,这些组织不光遵循X/Open组织定义的行业技术标准,同事也参与标准的制定。下图展示了open group目前主要成员(官网截图):
可以看到,华为也在其列。
其中,DTP即表示分布式事务处理(Distributed Transaction Processing),简称DTP。
所以X/Open DTP模型即X/Open 组织提出的分布式事务处理方案模型。
(1)DTP的五个基本模型元素
- 应用程序(Application Program ,简称AP):用于定义事务边界(即定义事务的开始和结束),并且在事务边界内对资源进行操作;
- 资源管理器(Resource Manager,简称RM):如数据库、文件系统等,并提供访问资源的方式;
- 事务管理器(Transaction Manager ,简称TM):负责分配事务唯一标识,监控事务的执行进度,并负责事务的提交、回滚等;
- 通信资源管理器(Communication Resource Manager,简称CRM):控制一个TM域(TM domain)内或者跨TM域的分布式应用之间的通信;
- 通信协议(Communication Protocol,简称CP):提供的分布式应用节点之间的底层通信服务
(2)XA规范
XA 是指由 X/Open 组织提出的分布式事务处理的规范,XA 规范主要定义了事务管理器(Transaction Manager)和资源管理器(Resource Manager)之间的接口,并对二阶段提交协议进行了优化,定义了两阶段提交协议中需要使用到的接口。
XA规范最主要的作用是,就是定义了RM-TM的交互接口,上图更加清晰了演示了XA规范在DTP模型中发挥作用的位置,从下图中可以看出来,XA仅仅出现在RM和TM的连线上。
2、二阶段提交
二阶段提交(Two Phase Commit)简称2pc,就是将整个事务分成准备和提交两个阶段。第一阶段为准备阶段,第二阶段为提交阶段。,其中事务的发起者称协调者(事务管理器),事务的执行者称参与者。
处理流程:
- 准备阶段(第一阶段):
- 协调者节点向所有参与者节点询问是否可以执行提交操作,并开始等待各参与者节点的响应。
- 参与者节点执行询问发起为止的所有事务操作,并将Undo信息和Redo信息写入日志。(Undo日志是记录修改前的数据,用于数据库回滚,Redo日志是记录修改后的数据,用于提交事务后写入数据文件)
- 各参与者节点响应协调者节点发起的询问。如果参与者节点的事务操作实际执行成功,则它返回一个"同意"消息;如果参与者节点的事务操作实际执行失败,则它返回一个"中止"消息。
当协调者节点从所有参与者节点获得的相应消息都为"同意"时:
-
提交阶段-成功(第二阶段)
- 协调者节点向所有参与者节点发出"正式提交"的请求。
- 参与者节点正式完成操作,并释放在整个事务期间内占用的资源。
- 参与者节点向协调者节点发送"完成"消息。
- 协调者节点收到所有参与者节点反馈的"完成"消息后,完成事务。
如果任一参与者节点在第一阶段返回的响应消息为"终止",或者 协调者节点在第一阶段的询问超时之前无法获取所有参与者节点的响应消息时:
- 提交阶段-失败(第二阶段):
- 协调者节点向所有参与者节点发出"回滚操作"的请求。
- 参与者节点利用之前写入的Undo信息执行回滚,并释放在整个事务期间内占用的资源。
- 参与者节点向协调者节点发送"回滚完成"消息。
- 协调者节点收到所有参与者节点反馈的"回滚完成"消息后,取消事务。
3、三阶段提交
我们需要明白一个概念,服务的数据是私有的,外部只能通过服务暴露的API访问这些数据,因此在数据库层面实现的分 布式事务不再可行。
Saga这个术语最早出现在普林斯顿大学研究人员发表的一篇关于数据库事务的论文中,这篇论文可在这 里下载:ftp://ftp.cs.princeton.edu/reports/1987/070.pdfo
企业应用在处理几乎每一个请求的过程中,都需要跟数据库打交道。企业应用的开发者 使用大量成熟的编程框架和函数库来简化事务管理。一些编程框架和函数库提供了 API,用 于显式地开始、提交或回滚事务。其他框架,例如Spring框架,则提供了注解式的机制,Spring采用@Transcaltional注解来让方法调用自动地在事务范围内完成。这些机制让编 写事务性的业务逻辑变得简单和透明。
createOrder()操作会更新多个服务中的数据,每个服务都有自己私有的数据库,如何维护这些服务之间数据的一致性。
4、TCC
5、本地消息表
6、MQ事务
7、Sage事务
各方案的性能参数比较
参考资料
微服务架构设计模式(克里森·查尔斯 著)
百度百科