C(Consistency)一致性 每一次读取都会让你获得最新的写入结果算法
A (Availability)可用性 每一个节点(若是没有失败),总能执行查询(读取和写入)操做网络
P (Partition Tolerance)分区容忍性 即便节点之间的链接关闭,其余两个属性也会获得保证分布式
CAP理论认为,任何联网的共享数据系统智能实现三个属性中的两个,可是能够经过明确处理分区,优化一致性和可用性,从而实现三者之间的某种权衡优化
不少文章和博客里提到,zookeeper是一种提供强一致性的服务,在分区容错性和可用性上作了必定折中,这和CAP理论是吻合的。但实际上zookeeper提供的只是单调一致性。spa
缘由:
1. 假设有2n+1个server,在同步流程中,leader向follower同步数据,当同步完成的follower数量大于 n+1时同步流程结束,系统可接受client的链接请求。若是client链接的并不是同步完成的follower,那么获得的并不是最新数据,但能够保证单调性。
2. follower接收写请求后,转发给leader处理;leader完成两阶段提交的机制。向全部server发起提案,当提案得到超过半数(n+1)的server认同后,将对整个集群进行同步,超过半数(n+1)的server同步完成后,该写请求完成。若是client链接的并不是同步完成follower,那么获得的并不是最新数据,但能够保证单调性。日志
用分布式系统的CAP原则来分析Zookeeper:
(1)C: Zookeeper保证了最终一致性,在十几秒能够Sync到各个节点.
(2)A: Zookeeper保证了可用性,数据老是可用的,没有锁.而且有一大半的节点所拥有的数据是最新的,实时的. 若是想保证取得是数据必定是最新的,须要手工调用Sync()
(2)P: 有2点须要分析的.
① 节点多了会致使写数据延时很是大,由于须要多个节点同步.
② 节点多了Leader选举很是耗时, 就会放大网络的问题. 能够经过引入 observer节点缓解这个问题.code
在分布式系统中,为了保证数据的高可用,一般咱们会将数据保留多个副本(replica), 这些副本会放置在不一样的物理机器上。为了对用户提供正确的curd等语意,咱们须要保证这些放置在不一样无力机器上的副本是一致的server
为了解决这种分布式一致性问题,提出了不少典型的协议和算法,比较著名的是二阶段提交协议,三阶段提交协议和paxos算法。blog
在分布式系统中,各个节点之间在物理上相互独立,经过网络进行沟通和协调。因为存在事务机制,能够保证每一个独立节点上的数据操做能够知足ACID。可是,相互独立的节点之间没法准确地知道其余节点的事务执行状况。因此从理论上来说,两台机器没法达到一致的状态。若是想让分布式部署的多台机器中的数据保持一致性,那么就要保证在全部节点数据的写操做,要么所有都执行,要么所有都不执行。可是,一台机器在执行本地事务的时候没法知道其余机器中的本地事务的执行结果,因此它也就不知道本次事务到底应该commit仍是rollback。因此,常规的解决办法就是引入一个"协调者"的组件来统一调度全部分布式节点的执行。事务
二阶段提交的算法思路能够归纳为: 参与者将操做成败通知协调者,再由协调者根据全部参与者的反馈情报决定各参与者是否要提交操做仍是停止操做。
二阶段是指: 第一阶段 - 请求阶段(表决阶段) 第二阶段 - 提交阶段(执行阶段)
(1) 请求阶段(表决):
事务协调者通知每一个参与者准备提交或取消事务,而后进入表决过程,参与者要么在本地执行事务,写本地的redo和undo日志,但不提交,到达一种"万事俱备,只欠东风"的状态。请求阶段,参与者将告知协调者本身的决策: 赞成(事务参与者本地做业执行成功)或取消(本地做业执行故障)
(2) 提交阶段(执行):
在该阶段,写调整将基于第一个阶段的投票结果进行决策: 提交或取消
当且仅当全部的参与者赞成提交事务,协调者才通知全部的参与者提交事务,不然协调者将通知全部的参与者取消事务
参与者在接收到协调者发来的消息后将执行响应的操做
2 两阶段提交的缺点
1.同步阻塞问题。执行过程当中,全部参与节点都是事务阻塞型的。
当参与者占有公共资源时,其余第三方节点访问公共资源不得不处于阻塞状态。
2.单点故障。因为协调者的重要性,一旦协调者发生故障。
参与者会一直阻塞下去。尤为在第二阶段,协调者发生故障,那么全部的参与者还都处于锁定事务资源的状态中,而没法继续完成事务操做。(若是是协调者挂掉,能够从新选举一个协调者,可是没法解决由于协调者宕机致使的参与者处于阻塞状态的问题)
3.数据不一致。在二阶段提交的阶段二中,当协调者向参与者发送commit请求以后,发生了局部网络异常或者在发送commit请求过程当中协调者发生了故障,这回致使只有一部分参与者接受到了commit请求。
而在这部分参与者接到commit请求以后就会执行commit操做。可是其余部分未接到commit请求的机器则没法执行事务提交。因而整个分布式系统便出现了数据不一致性的现象。
3 两阶段提交没法解决的问题
当协调者出错,同时参与者也出错时,两阶段没法保证事务执行的完整性。
考虑协调者在发出commit消息以后宕机,而惟一接收到这条消息的参与者同时也宕机了。
那么即便协调者经过选举协议产生了新的协调者,这条事务的状态也是不肯定的,没人知道事务是否被已经提交。
三阶段提交协议在协调者和参与者中都引入超时机制,而且把两阶段提交协议的第一个阶段分红了两步: 询问,而后再锁资源,最后真正提交。
(1) canCommit阶段
3PC的canCommit阶段其实和2PC的准备阶段很像。协调者向参与者发送commit请求,参与者若是能够提交就返回yes响应,不然返回no响应
(2) preCommit阶段
协调者根据参与者canCommit阶段的响应来决定是否能够继续事务的preCommit操做。根据响应状况,有下面两种可能:
a) 协调者从全部参与者获得的反馈都是yes:
那么进行事务的预执行,协调者向全部参与者发送preCommit请求,并进入prepared阶段。参与泽和接收到preCommit请求后会执行事务操做,并将undo和redo信息记录到事务日志中。若是一个参与者成功地执行了事务操做,则返回ACK响应,同时开始等待最终指令
b) 协调者从全部参与者获得的反馈有一个是No或是等待超时以后协调者都没收到响应:
那么就要中断事务,协调者向全部的参与者发送abort请求。参与者在收到来自协调者的abort请求,或超时后仍未收到协调者请求,执行事务中断。
(3) doCommit阶段
协调者根据参与者preCommit阶段的响应来决定是否能够继续事务的doCommit操做。根据响应状况,有下面两种可能:
a) 协调者从参与者获得了ACK的反馈:
协调者接收到参与者发送的ACK响应,那么它将从预提交状态进入到提交状态,并向全部参与者发送doCommit请求。参与者接收到doCommit请求后,执行正式的事务提交,并在完成事务提交以后释放全部事务资源,并向协调者发送haveCommitted的ACK响应。那么协调者收到这个ACK响应以后,完成任务。
b) 协调者从参与者没有获得ACK的反馈, 也多是接收者发送的不是ACK响应,也多是响应超时:
执行事务中断。
对于协调者(Coordinator)和参与者(Cohort)都设置了超时机制(在2PC中,只有协调者拥有超时机制,即若是在必定时间内没有收到cohort的消息则默认失败)。
在2PC的准备阶段和提交阶段之间,插入预提交阶段,使3PC拥有CanCommit、PreCommit、DoCommit三个阶段。
PreCommit是一个缓冲,保证了在最后提交阶段以前各参与节点的状态是一致的。
维基百科:
三阶段提交是“非阻塞”协议。
三阶段提交在两阶段提交的第一阶段与第二阶段之间插入了一个准备阶段,
使得原先在两阶段提交中,参与者在投票以后,因为协调者发生崩溃或错误,
而致使参与者处于没法知晓是否提交或者停止的“不肯定状态”所产生的可能至关长的延时的问题得以解决。 举例来讲,假设有一个决策小组由一个主持人负责与多位组员以电话联络方式协调是否经过一个提案,以两阶段提交来讲,主持人收到一个提案请求,打电话跟每一个组员询问是否经过并统计回复,而后将最后决定打电话通知各组员。
要是主持人在跟第一位组员通完电话后失忆,而第一位组员在得知结果并执行后老人痴呆,那么即便从新选出主持人,也没人知道最后的提案决定是什么,也许是经过,也许是驳回,无论你们选择哪种决定,都有可能与第一位组员已执行过的真实决定不一致,老板就会不开心认为决策小组沟通有问题而解雇。
三阶段提交便是引入了另外一个步骤,主持人打电话跟组员通知请准备经过提案,以免没人知道真实决定而形成决定不一致的失业危机。
为何可以解决二阶段提交的问题呢?
回到刚刚提到的情况,在主持人通知完第一位组员请准备经过后两人意外失忆,即便没人知道全体在第一阶段的决定为什么,全体决策组员仍能够从新协调过程或直接否决,不会有不一致决定而失业。
那么当主持人通知彻底体组员请准备经过并获得你们的再次肯定后进入第三阶段,
当主持人通知第一位组员请经过提案后两人意外失忆,这时候其余组员再从新选出主持人后,
仍能够知道目前至少是处于准备经过提案阶段,表示第一阶段你们都已经决定要经过了,此时即可以直接经过。
若是进入PreCommit后,Coordinator发出的是abort请求,假设只有一个Cohort收到并进行了abort操做,
而其余对于系统状态未知的Cohort会根据3PC选择继续Commit,此时系统状态发生不一致性。
目前还有一种重要的算法就是Paxos算法,Zookeeper采用的就是Paxos算法的改进。