如果说使用分布式系统带来最大的挑战,应该就是分布式事务了。当使用单体应用的时候,所有接口都是在一个线程内调用,事务相对来说比较好控制;而且在使用单数据库操作的时候,事务控制更加简单。然而当我们将业务数据进行了分库分表存储,并且引入了分布式系统部署后,问题变得复杂起来。“如何保证分布式系统中的事务一致性?”,这是java面试中最喜欢问的一个问题,在笔者面试的时候无数次遇到过这个问题。经过查阅无数书籍,很遗憾的是,笔者发现目前在业界内还没有一个十全十美的解决方案,但是聪明的架构师和程序员们想出了很多折中的方案来处理,后面会尝试说明。
本文先讲讲关于分布式事务的一些理论基础。
ACID
首先说下什么是数据库事务。数据库事务是数据库运行中的一个逻辑工作单位,工作单元内的一系列sql命令具有原子性操作的特点,这些命令要么全部成功执行,要么全部撤销或不执行,如果是后者,则表现为数据库内的最终数据没有发生任何改变。事务通常由数据库中的事务管理子系统负责处理。
ACID是指数据库事务正确执行的四个基本要素的缩写。包含:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。
原子性:整个事务中的所有操作,要么全部完成,要么全部不完成,不存在中间状态。
一致性:事务必须始终保持系统处于一致的状态,不管在任何给定的时间并发事务有多少。
隔离性:隔离状态执行事务,使它们好像是系统在给定时间内执行的唯一操作。
持久性:在事务完成以后,该事务对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。
这里着重说说隔离性,常见的数据库事务有4中隔离级别,分别为:
1.未授权读取
读未提交(Read Uncommitted),允许脏读,隔离级别最低。
2.授权读取
读已提交(Read Committed),只允许获取已经被提交的数据,不可重复读。
3.可重复读取
Repeatable Read,保证在事务处理过程中,多次读取同一数据时,其值都和事务开始时刻一致。但可能幻读。
4.串行化
Serializable,最严格的隔离级别,所有事务串行执行。
对于几个名词概念再进行下整理:
脏读:事务A读取了事务B未提交的数据,并在此基础上做了其他操作;
不可重复读:事务A读取了事务B的已提交记录;
幻读:事务A读取了事务B已提交的新增数据;
在mysql中,事务相关的日志文件为redo和undo文件,redo记录事务修改后的数据,undo记录事务前的原始数据。由于事务随时可能需要回滚,所以在mysql执行事务过程中这两个文件都会被写入数据。步骤如下:
1.记录undo/redo log,确保日志刷到磁盘上持久存储;
2.更新数据记录,缓存操作并异步刷盘;
3.提交事务,在redo log中写入commit记录。
3.1清理undo段信息;
3.2释放锁资源;
3.3刷新redo日志,确保redo日志落盘,即使修改的数据页没有更新到磁盘,只要日志完成就能确保事务一致性;
3.4清理savepoint列表;
CAP
ACID是数据库层面的理论,那么CAP就是针对于分布式系统的理论。CAP理论是Eric Brewer在2000年7月份提出,包含如下三个要素Consistency(一致性)、Availability(可用性)和Partition-Tolerance(分区容忍性)。
C: Consistency,一致性。在分布式系统中的所有数据备份,在同一时刻具有同样的值,所有节点在同一时刻读取的数据都是最新的数据副本。
A: Availability,可用性。完全的可用性指的是在任何故障模型下,服务都会在有限的时间内处理完成并进行响应。
P: Partition tolerance,分区容忍性。单个节点宕机后,但系统仍然可继续工作。
CAP理论证明,任何分布式系统只可同时满足以上两点,无法三者兼顾。由于关系型数据库是单节点无复制的,因此不具有分区容忍性,但是具有一致性和可用性;而分布式的服务化系统天生满足分区容忍性,那么我们必须在一致性和可用性之间进行权衡。如果在网络上有消息丢失,也就足出现了网络分区,则复制操作可能会被延后,如果这时我们的使用方等待复制完成再返回,则可能导致在有限时间内无法返回,就失去了可用性;而如果使用方不等待复制完成,而在主分片写完后直接返回,则具有了可用性,但是失去了一致性。
简言之,在CAP理论下我们可以同时实现CP和AP。CP的实现就是拒绝分布式事务失败的响应;AP的理论实现就是最终一致性。关于最终一致性,请见下文:
BASE
BASE模型是eBay架构师Dan Pritchett提出的,是对CAP理论的延伸,核心思想是即使无法做到强一致性(Strong Consistency,CAP的一致性就是强一致性),但应用可以采用适合的方式达到最终一致(Eventual Consitency)。
BASE模型包括Basically Available(基本可用)、Soft state(软状态)和Eventually consistent(最终一致性)。
BA:Basically Available,基本可用。
S:Soft state,软状态,状态可以在一段时间内不同步。
E:Eventually consistent,最终一致性,在一定时间内,系统内状态达到最终一致。
BASE模型的一个实现思路是,在系统短暂的不一致时间内,请求处理处于临时状态中,系统在进行每步操作时,通过记录每个临时状态,在系统出现故障时可以从这些中间状态继续处理未完成的请求或者退回到原始状态,达到状态的最终一致。
关于分布式事务除了有上述的理论支撑,还有一些已经实现了的分布式协议供我们参考。后面的文章我们针对几种常间的分布式协议进行总结。