分布式原理|分布式数据库理论知识之CAP理论、ACID原则及分布式事务一致性算法

1 CAP理论 分布式数据库的设计遵循CAP理论,即一个分布式系统不能同时满足Consistency(一致性)、Availability(可用性)和Partition Tolerance(分区容忍性)这三个基本需求。
一致性(Consistency)
一致性指的是更新操作成功并返回客户端后,分布式集群中每个节点都返回相同的、最新的数据。
对于一致性,可以从客户端和服务端两个不同的视角来看:
从客户端来看,一致性主要指的是多并发访问时更新过的数据如何获取的问题;
从服务端来看,则是更新如何复制到整个分布式系统,以保证数据的最终一致性。
在多进程并发访问时,根据获取更新过的数据的不同策略,一致性又分为强一致性、弱一致性和最终一致性。
对于关系型数据库,要求更新过的数据能被后续的访问都能看到,这是强一致性。
如果能容忍后续的部分或者全部访问不到,则是弱一致性。
如果经过一段时间后要求能访问到更新后的数据,则是最终一致性。
可用性(Availability)
可用性指的是系统服务一直可用,在合理的时间内返回读写请求的响应。
对于一个可用的分布式系统,衡量系统可用性的时候,一般通过停机时间来计算的。
通常说金融核心业务系统的可用性水平达到5个9,即全年停机时间不超过 (1-0.99999) * 365 * 24 * 60 = 5.256 min,这是一个极高的要求。
分区容忍性(Partition Tolerance)
分区容忍性指的是分布式系统在网络分区出现故障时,仍然能够对外提供满足一致性和可用性的服务。
在分布式数据库系统中,分区容忍性和扩展性紧密关联,一个好的分区容忍性能够保证当其中几台机器故障或者网络异常后,能够快速的进行故障隔离不影响其它机器的正常运行;也能够保证系统扩展性,节点的新增和删除做到对业务无感知。
CAP的权衡
根据CAP理论,无法同时满足一致性、可用性和分区容忍性。但是在分布式数据库系统中,分区容忍性是必须的,分区是始终会存在的,因此需要在一致性和可用性之间进行权衡。
CP without A:分布式系统容许系统停机或者长时间无响应,一旦发生网络故障或者消息丢失等情况,就要牺牲用户的体验,等待所有数据全部一致了之后再让用户访问系统。传统的分布式数据库事务都属于这种模式,对于金融行业的分布式数据库产品而言,优先保证数据的一致性。
AP without C:分布式系统中允许数据不一致,一旦分区发生,节点之间可能会失去联系,为了高可用,每个节点只能用本地数据提供服务,而这样会导致全局数据的不一致性。现在众多的NoSQL都属于此类。
在实际的分布式数据库系统中,基于分片解决扩展性问题并可以实现负载均衡,当某个分片服务不可用时,只会影响部分业务,即服务降级。同时基于多副本构成集群架构,提升系统的高可用。
2 ACID原则 ACID指的是数据库系统中事务所具有的四个特性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。
原子性:一个事务中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
一致性:在事务开始之前和事务结束以后,数据库的完整性限制没有被破坏。
隔离性:当两个或者多个事务并发访问数据库的同一数据时所表现出的相互关系。
持久性:在事务完成以后,该事务对数据库所作的更改便持久地保存在数据库之中,并且是完全的。
3 分布式事务一致性算法 在分布式系统中,每一个机器节点虽然都能够明确地知道自己在进行事务操作过程中的结果是成功或失败,但却无法直接获取到其他分布式节点的操作结果。因此,当一个事务操作需要跨越多个分布式节点的时候,为了保持事务处理的ACID特性,就需要引入一个称为"协调者"的组件来统一调度所有分布式节点的执行逻辑,这些被调度的分布式节点则被称为"参与者"。协调者负责调度参与者的行为,并最终决定这些参与者是否要把事务真正进行提交。基于以上原则,分布式事务一致性算法主要包括2PC、3PC、Paxos和Raft。
2PC(two-phase commit) 二阶段提交2PC是一致性协议算法,可以保证数据的强一致性,该算法能够解决很多临时性系统故障(包括进程、网络节点、通信等故障),被广泛地使用于关系型数据库系统中。2PC协议中系统分为协调者和参与者,整个过程分为两个阶段:
阶段1:请求阶段
在请求阶段,协调者将通知事务参与者准备提交或取消事务,然后进入表决过程。在表决过程中,参与者将告知协调者自己的决策:同意(事务参与者本地作业执行成功)或取消(本地作业执行故障)。
【分布式原理|分布式数据库理论知识之CAP理论、ACID原则及分布式事务一致性算法】阶段2:提交阶段
在该阶段,协调者将基于第一个阶段的投票结果进行决策:提交或取消。当且仅当所有的参与者同意提交事务协调者才通知所有的参与者提交事务,否则协调者将通知所有的参与者取消事务。参与者在接收到协调者发来的消息后将执行响应的操作。
2PC协议的优点是原理简单、实现方便,但也有以下缺点:
同步阻塞:在二阶段提交的执行过程中,所有参与该事务操作的逻辑都处于阻塞状态,也就是说,各个参与者在等待其他参与者响应的过程中,将无法进行其他任何操作。
单点问题:协调者的角色在整个二阶段提交协议中起到了非常重要的作用。一旦协调者出现问题,那么整个二阶段提交流程将无法运转,更为严重的是,如果协调者是在阶段二中出现问题的话,那么其他参与者将会一直处于锁定事务资源的状态中,而无法继续完成事务操作。
数据不一致:在阶段二时,当协调者向所有的参与者发送Commit请求之后,发生了局部网络异常或者是协调者尚未发送完Commit请求之前自身发生了崩溃,导致最终只有部分参与者收到了Commit请求。于是,这部分收到了Commit请求的参与者就会进行事务的提交,而其他没有收到Commit请求的参与者则无法进行事务提交,于是整个分布式系统便出现了数据不一致现象。
太过保守:二阶段提交协议没有设计较为完善的容错机制,任何一个节点的失败都会导致整个事务的失败。
3PC(three-phase commit) 3PC协议在协调者和参与者中都引入超时机制,并且把两阶段提交协议的第一个阶段拆分成了两步:询问,然后再锁资源,最后真正提交,包括CanCommit、PreCommit和doCommit三个阶段。
1)CanCommit阶段
3PC的CanCommit阶段和2PC的准备阶段很像。协调者向参与者发送commit请求,参与者如果可以提交就返回Yes响应,否则返回No响应。
2)PreCommit阶段
协调者根据参与者的反应情况来决定是否可以继续事务的PreCommit操作。根据响应情况,有以下两种可能。

  1. 假如协调者从所有的参与者获得的反馈都是Yes响应,那么就会进行事务的预执行:
  • 发送预提交请求。协调者向参与者发送PreCommit请求,并进入Prepared阶段。
  • 事务预提交。参与者接收到PreCommit请求后,会执行事务操作,并将undo和redo信息记录到事务日志中。
  • 响应反馈。如果参与者成功的执行了事务操作,则返回ACK响应,同时开始等待最终指令。
  1. 假如有任何一个参与者向协调者发送了No响应,或者等待超时之后,协调者都没有接到参与者的响应,那么就中断事务:
  • 发送中断请求。协调者向所有参与者发送abort请求。
  • 中断事务。参与者收到来自协调者的abort请求之后(或超时之后,仍未收到Cohort的请求),执行事务的中断。
3)DoCommit阶段
该阶段进行真正的事务提交,也可以分为以下两种情况:
  1. 执行提交
  • 发送提交请求。协调者接收到参与者发送的ACK响应,那么他将从预提交状态进入到提交状态。并向所有参与者发送doCommit请求。
  • 事务提交。参与者接收到doCommit请求之后,执行正式的事务提交。并在完成事务提交之后释放所有事务资源。
  • 响应反馈。事务提交完之后,向协调者发送ACK响应。
  • 完成事务。协调者接收到所有参与者的ACK响应之后,完成事务。
  1. 中断事务
  • 协调者没有接收到参与者发送的ACK响应(可能是接受者发送的不是ACK响应,也可能响应超时),那么就会执行中断事务。
3PC协议降低了参与者阻塞范围,并能够在出现单点故障后继续达成一致。缺点是引入 preCommit阶段,在这个阶段如果出现网络分区,协调者无法与参与者正常通信,参与者依然会进行事务提交,造成数据不一致。
Paxos和Raft 2PC/3PC用于保证多个数据分片上操作的原子性,这些数据分片可能存在于不同的服务器上,2PC/3PC保证这些操作要么全部成功,要么全部失败。Paxos和Raft则是用于保证同一个数据分片的多个数据副本之间的数据一致性。
Paxos算法属于多数派算法,主要解决数据分片的单点问题,目的是让整个集群对某个值的变更达成一致。集群中的任何一个节点都可以提出要修改某个数据的提案,是否通过这个提案取决于这个集群中是否有超过半数的节点同意,所以Paxos算法建议集群中的节点为奇数。
Raft算法是简化版的Paxos, Raft划分成三个子问题:一是Leader Election;二是Log Replication;三是Safety。Raft 定义了三种角色Leader、Follower、Candidate,最开始大家都是Follower,当Follower监听不到Leader,就可以自己成为Candidate,发起投票,选出新的leader。
1PC一阶段提交 1PC协议阶段就是从应用程序向数据库发出提交请求到数据库完成提交或回滚之后,将结果返回给应用程序的过程。一阶段提交不需要“协调者”角色,各结点之间不存在协调操作,因此其事务执行时间比两阶段提交要短,但是提交的“危险期”是每一个事务的实际提交时间,相比于两阶段提交,一阶段提交出现在“不一致”的概率就变大了。
在分布式系统中如果存在跨分片的分布式事务,1PC提交并不能保证数据的一致性。像GoldenDB分布式数据库就是通过1PC协议+全局活跃事务ID(GTID)来实现分布式事务。

    推荐阅读