vlambda博客
学习文章列表

分布式事务的点点滴滴

概念

最近着手把微服务项目的数据库进行分库分表,不可避免的要增加分布式事务的考虑,所以在此把相关知识点梳理一下。本专题将会分为三篇,从分布式事务的概念到各种理论和协议。

讲分布式事务之前先做个扫盲,了解几个概念:

1.微服务

以下内容来自维基百科

微服务(英语:Microservices)是一种软件架构风格,
它是以专注于单一责任与功能的小型功能区块 (Small Building Blocks) 为基础,
利用模块化的方式组合出复杂的大型应用程序,
各功能区块使用与语言无关 (Language-Independent/Language agnostic)
的API集相互通信。
微服务的起源是由 Peter Rodgers 博士于 2005 年度云计算博览会
提出的微 Web 服务(Micro-Web-Service)开始,
Juval Löwy 则是与他有类似的前导想法,
将类别变成细粒服务(granular services),以作为微软下一阶段的软件架构,
其核心想法是让服务是由类似 Unix 管道的访问方式使用,
而且复杂的服务背后是使用简单 URI 来开放接口,任何服务,
任何细粒都能被开放(exposed)。这个设计在 HP 的实验室被实现,
具有改变复杂软件系统的强大力量。

2.分布式

以下内容来自维基百科

分布式系统有很多不同的定义,
一般认为:“一个分布式系统是一些独立的计算机集合,
但是对这个系统的用户来说,系统就像一台计算机一样。”
这个定义有两方面的含义:
第一,从硬件角度来讲,每台计算机都是自主的;
第二,从软件角度来讲,用户将整个系统看做是一台计算机。
这两者都是必需的,缺一不可

3.事务

以下内容来自维基百科

数据库事务(简称:事务)是数据库管理系统执行过程中的一个逻辑单位,
由一个有限的数据库操作序列构成。
数据库事务通常包含了一个序列的对数据库的读/写操作。
包含有以下两个目的:
为数据库操作序列提供了一个从失败中恢复到正常状态的方法,
同时提供了数据库即使在异常状态下仍能保持一致性的方法。
当多个应用程序在并发访问数据库时,可以在这些应用程序之间提供一个隔离方法,
以防止彼此的操作互相干扰。
通俗点讲就是:数据库事务可以确保该事务范围内的所有操作都可以全部成功或者全部失败。
如果事务失败,那么效果就和没有执行这些SQL一样,不会对数据库数据有任何改动。

3.1 分布式事务的起源:

在单体架构中,我们可以通过数据库层面对事务的支持来保证业务上的事务操作。
但是随着微服务架构的普及,一个大型业务系统往往由若干个子系统构成,
这些子系统又拥有各自独立的数据库。往往一个业务流程需要由多个子系统共同完成,
而且这些操作可能需要在一个事务中完成。此时,我们就需要在数据库之上通过某种手段,
实现跨数据库的事务支持,这也就是大家常说的“分布式事务”。
分布式事务涉及到操作多个数据库的事务,分布式事务的参与者、支持事务的服务器、
资源服务器以及事务管理器分别位于分布式系统的不同节点上。
一个分布式事务可以看作是由多个分布式的操作序列组成的,
通常可以把这一系列分布式的操作序列称为子事务,
但由于在分布式事务中,各个子事务的执行是分布式的,
因此要实现一种能够保证 ACID 特性的分布式事务处理系统就显得格外复杂。

3.2 分布式事务的两个典型应用场景:

1.数据库分库分表:
在单库单表场景下,当业务数据量达到单库单表的极限时,就需要考虑分库分表,
将之前的单库单表拆分成多库多表;分库分表之后,原来在单个数据库上的事务操作,
可能就变成跨多个数据库的操作,此时就需要使用分布式事务。

2.业务服务化
业务服务化即业务按照面向服务(SOA)的架构拆分整个网站系统,所有的业务操作都以服务的方式对外发布,
跨应用、跨服务的操作需要使用分布式事务才能保证数据的一致性。

3.3 分布式事务涉及到的几个理论:

3.3.1.CAP:
分布式系统不可能同时满足
一致性(C:Consistency)、
可用性(A:Availability)、
分区容忍性(P:Partition Tolerance)、
最多只能同时满足其中两项。

Consistency 一致性:一致性指的是多个数据副本是否能保持一致的特性,
在一致性的条件下,系统在执行数据更新操作之后能够从一致性状态转移到另一个一致性状态。
对系统的一个数据更新成功之后,如果所有用户都能够读取到最新的值,该系统就被认为具有强一致性。

Availability 可用性:可用性指分布式系统在面对各种异常时可以提供正常服务的能力,
可以用系统可用时间占总时间的比值来衡量,4 个 9 的可用性表示系统 99.99% 的时间是可用的。
在可用性条件下,要求系统提供的服务一直处于可用的状态,
对于用户的每一个操作请求总是能够在有限的时间内返回结果。

Parttition Tolerance 分区容忍性:网络分区指分布式系统中的节点被划分为多个区域,
每个区域内部可以通信,但是区域之间无法通信。
在分区容忍性条件下,分布式系统在遇到任何网络分区故障的时候,
仍然需要能对外提供一致性和可用性的服务,除非是整个网络环境都发生了故障。

关于CAP的知乎高赞解释:

一个分布式系统里面,节点组成的网络本来应该是连通的。然而可能因为一些故障,使得有些节点之间不连通了,  
整个网络就分成了几块区域。数据就散布在了这些不连通的区域中。这就叫分区。
当你一个数据项只在一个节点中保存,那么分区出现后,和这个节点不连通的部分就访问不到这个数据了。
这时分区就是无法容忍的。提高分区容忍性的办法就是一个数据项复制到多个节点上,
那么出现分区之后,这一数据项就可能分布到各个区里。容忍性就提高了。
然而,要把数据复制到多个节点,就会带来一致性的问题,
就是多个节点上面的数据可能是不一致的。
要保证一致,每次写操作就都要等待全部节点写成功,而这等待又会带来可用性的问题。
总的来说就是,数据存在的节点越多,分区容忍性越高,但要复制更新的数据就越多,
一致性就越难保证。为了保证一致性,更新所有节点数据所需要的时间就越长,可用性就会降低。

综上,CAP 理论实际上是要在可用性和一致性之间做权衡。
可用性和一致性往往是冲突的,很难使它们同时满足。在多个节点之间进行数据同步时,
为了保证一致性(CP),不能访问未同步完成的节点,也就失去了部分可用性;
为了保证可用性(AP),允许读取所有节点的数据,但是数据可能不一致。
通常采取的策略是保证可用性,牺牲部分一致性,只确保最终一致性。
当然,牺牲一致性,并不是完全不管数据的一致性,否则数据是混乱的,
那么系统可用性再高分布式再好也没有了价值。牺牲一致性,
只是不再要求关系型数据库中的强一致性,而是只要系统能达到最终一致性即可,
考虑到客户体验,这个最终一致的时间窗口,要尽可能的对用户透明,
也就是需要保障“用户感知到的一致性”。
通常是通过数据的多份异步复制来实现系统的高可用和数据的最终一致性的,
“用户感知到的一致性”的时间窗口则取决于数据复制到一致状态的时间。

3.3.2.BASE:
BASE理论是指,  
Basically Available(基本可用)、
Soft-state( 软状态/柔性事务)、
Eventual Consistency(最终一致性)。
是基于CAP定理演化而来,是对CAP中一致性和可用性权衡的结果。
核心思想:即使无法做到强一致性,但每个业务根据自身的特点,采用适当的方式来使系统达到最终一致性。

基本可用BA:(Basically Available ):指分布式系统在出现故障的时候,允许损失部分可用性,保证核心可用。
但不等价于不可用。比如:搜索引擎0.5秒返回查询结果,但由于故障,2秒响应查询结果;
网页访问过大时,部分用户提供降级服务等。简单来说就是基本可用。

软状态S:(Soft State):软状态是指允许系统存在中间状态,并且该中间状态不会影响系统整体可用性。
即允许系统在不同节点间副本同步的时候存在延时。简单来说就是状态可以在一段时间内不同步。

最终一致性E:(Eventually Consistent):系统中的所有数据副本经过一定时间后,最终能够达到一致的状态,
不需要实时保证系统数据的强一致性。最终一致性是弱一致性的一种特殊情况。

BASE理论面向的是大型高可用可扩展的分布式系统,通过牺牲强一致性来获得可用性。
ACID是传统数据库常用的概念设计,追求强一致性模型。
简单来说就是在一定的时间窗口内, 最终数据达成一致即可。
3.3.3.柔性事务和刚性事务:
刚性事务满足ACID理论
ACID能够保证事务的强一致性,即数据是实时一致的。
这在本地事务中是没有问题的,在分布式事务中,
强一致性会极大影响分布式系统的性能,因此分布式系统中遵循BASE理论即可。
但分布式系统的不同业务场景对一致性的要求也不同。
如交易场景下,就要求强一致性,此时就需要遵循ACID理论,
而在注册成功后发送短信验证码等场景下,并不需要实时一致,
因此遵循BASE理论即可。
因此要根据具体业务场景,在ACID和BASE之间寻求平衡。
柔性事务满足BASE理论(基本可用,最终一致)

柔性事务分为:
两阶段型 2PC(two phase commitment)
补偿型TCC (try confirn/caclen
异步确保型 (通过信息中间件)
最大努力通知型。

分布式事务涉及到的概念讲完了,接下来两篇讲分别讲下分布式事务的一些指导理论和协议。