提到事务,很多人第一时间想到的是数据库的事务。所谓的数据库事务是指作为单个逻辑工作单元执行的多个数据库操作,要么同时成功,要么同时失败,它必须满足ACID特性,即:
上述是针对单库多表的情况下事务所需要满足的特性。在微服务架构下,随着业务服务的拆分以及数据库的拆分,会存在下图所示的场景,订单和库存分别拆分成了两个独立的数据库,当客户端发起一个下单操作时,需要在订单服务对应的数据库中创建订单,同时需要基于RPC通信调用库存服务完成商品库存的扣减。
在这样一个场景中,原本的单库事务操作就变成了多个数据库的事务操作,由于每个数据库的事务执行情况只有自己知道,比如订单数据库并不知道库存数据库的执行结果,这样就会导致订单数据库和库存数据库的数据不一致的问题,比如订单创建成功,库存扣减失败,就可能导致"超卖"问题。
这就是所谓的分布式事务场景,准确来说,分布式事务是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于分布式系统的不同节点上。
分布式事务问题也叫分布式数据一致性问题,简单来说就是如何在分布式场景中保证多个节点数据的一致性。分布式事务产生的核心原因在于存储资源的分布性,比如多个数据库,或者MySQL和Redis两种不同存储设备的数据一致性等。在实际应用中,我们应该尽可能地从设计层面避免分布式事务的问题,因为任何一种解决方案都会增加系统的复杂度。下面我们来了解一下分布式事务问题的常见解决方案。
X/Open DTP(X/Open Distributed Transaction Processing Reference Model)是X/Open这个组织定义的一套分布式事务的标准。这个标准提出了使用两阶段提交(2PC)来保证分布式事务的完整性。如下图所示,X/Open DTP中包含三种角色:
上图所展示的角色和关系与本地事务的原理基本相同,唯一不同的在于,如果此时RM代表数据库,那么TM需要能够管理多个数据库的事务,大致实现步骤如下:
为了更清晰地理解,可以参考下图所示的流程图,实际上这里会设计全局事务的概念,也就是说,在原本的单机事务下,会存在跨库事务的可见性问题,导致无法实现多节点事务的全局可控。而TM就是一个全局事务管理器,它可以管理多个资源管理器的事务。TM最终会根据各个分支事务的执行结果进行提交或者回滚,如果注册的所有分支事务中任何一个节点事务执行失败,为了保证数据的一致性,TM会触发各个RM的事务回滚操作。
TM和多个RM之间的事务控制,是基于XA协议来完成的。XA协议是X/Open提出的分布式事务处理规范,也是分布式事务处理的工业标准,它定义了xa_和ax_系列的函数原型及功能、约定等。目前Oracle、MySQL、DB2等都实现了XA接口,所以他们都可以作为RM。
上图中TM实现了多个RM事务的管理,实际上会设计两个阶段的提交,第一阶段是事务的准备阶段,第二阶段是事务的提交或者回滚阶段。这两个阶段都是由事务管理器发起的。两阶段提交协议的执行流程如下:
两阶段提交将一个事务的处理过程分为投票和执行两个阶段,它的优点在于充分考虑到了分布式系统的不可靠因素,并且采用非常简单的方式(两阶段提交)就把由于系统不可靠而导致事务提交失败的概率降到最小。当然,它也有以下缺点:
三阶段提交协议是两阶段提交协议的改进版本,它利用超时机制解决了同步阻塞的问题,三阶段提交协议的具体描述如下:
实际上,一旦超时,在三阶段提交协议下仍然可能出现数据不一致的情况,当然概率是比较小的。另外,最大的好处就是基于超时机制来避免资源的永久锁定。
不管是两阶段还是三阶段协议,都是数据一致性解决方案的实现,可以在实际应用中灵活的调整。
上面提到的两阶段提交和三阶段提交是XA协议解决分布式数据一致性问题的基本原理,但是这两种方案为了保持数据的强一致性,降低了可用性。实际上这里涉及分布式事务的两个理论模型。
CAP定理
简单来说它是指在分布式系统中不可能同时满足一致性(C: Consistency)、可用性(A: Availability)、分区容错性(P:Partition Tolerance)这三个基本需求,最多同时满足两个。
不同节点分布在不同的子网络中时,在内部子网络正常的情况下,由于某些原因导致这些子节点之间出现网络不通的情况,导致整个系统环境被切分成若干独立的区域,这就是网络分区。
CAP定理证明,在分布式系统中,要么满足CP、要么满足AP,不可能实现CAP或者CA。原因是网络通信并不是绝对可靠的,比如网络延时、网络异常等都会导致系统故障。而在分布式系统中,即便出现网络故障也需要保证系统仍然能够正常对外提供服务,所以在分布式系统中Partition Tolerance是必然存在的,也就是需要满足分区容错性。
如果是CA或者CAP这种情况,相当于网络百分之百可靠,否则当出现网络分区的情况时,为了保持数据的一致性,必须拒绝客户端的请求。但是如果拒绝了请求,就无法满足A,所以在分布式系统中不可能选择CA,因此只能有AP或者CP这两种选择。
BASE理论
BASE理论是由于CAP中一致性和可用性不可兼得而衍生出来的一种新的思想,BASE理论的核心思想是通过牺牲数据的强一致性来获得高可用性。它有如下三个特征:
BASE理论并没有要求数据的强一致性,而是允许数据在一段时间内是不一致的,但是数据最终会在某个时间点实现一致。在互联网产品中,大部分都会采用BASE理论来实现数据的一致,因为产品的可用性对于用户来说更加重要。
举个例子,在电商平台中用户发起一个订单的支付,不需要同步等待支付的执行结果,系统会返回一个支付处理中的状态到用户界面。对于用户来说,他可以从订单列表中看到支付的处理结果,而对于系统而言,当第三方支付处理成功之后,再更新该订单的支付状态即可。在这个场景中,虽然订单的支付状态和第三方的支付状态存在短期的不一致,但是用户却获得了更好的产品体验。