Zookeeper知识点

一、什么是二阶段提交(2pc)

阶段1:提交事务请求

协调者向所有参与者发送事务内容。参与者执行事务操作,并记录undo、redo日志,执行成功返回yes,否则返回no。

阶段2:执行事务提交

1.协调者从所有参与者获得是反馈都是yes时,就会向所有参与者发送commit请求。参与者执行事务提交操作,成功后发送ack消息。协调者收到ack消息,完成事务。

2.若协调者收到其中的一个是no,则会向所有参与者发送rollback请求。参与者使用undo日志进行回滚,完成后发送ack消息。协调者收到ack消息,完成事务中断。

缺点:同步阻塞、单点问题、脑裂、太过保守

二、什么是三阶段提交(3pc)

阶段1:canCommit

协调者发送一个包含事务内容的canCommit请求,等待参与者的相应。参与者自身认为可以顺利执行事务,会反馈yes,否则反馈no。

阶段2:preCommit

1.预提交

协调者收到所有的都是yes,就会执行事务预提交,发送preCommit请求。参与者收到preCommit请求后,会执行事务操作,记录undo和redo日志,反馈ack消息。

2.中断事务

若其中一个反馈了no,协调者就发送中断请求,参与者进行事务中断。

阶段3:doCommit

1.执行提交

协调者收到所有的ack,它会从预提交转到提交,发送doCommit请求。参与者进行事务提交,反馈ack消息。协调者确认ack,完成事务。

2.中断事务

协调者发送中断请求,参与者进行事务回滚。

三、ZAB协议(zk原子广播协议)

ZAB协议采用主备模型,保证了同一时刻集群中只有一个主进程广播服务器的状态变更。和2pc协议相似,主节点以广播的形式将事务Proposal发送到所有的从节点,等待从节点的反馈。一旦半数的机器进行了正确的反馈,主节点会发送commit消息,执行事务提交。

注意:如果集群中其他机器收到客户端的事务请求后,会转发给主节点,主节点再进行广播。

和2pc的区别

ZAB采用选举机制保证集群中主节点的可用性。

ZAB有超过半数的正常反馈,就可以执行事务提交。

ZAB必须保证一个全局的变更系列顺序,如果一个状态被处理了,那么在它之前的状态也一定被处理了。例如变更C需要依赖变更A和B。

四、Leader选举机制

1.发起投票

当leader挂掉后,余下的非Observer服务器把自己的状态变更为looking,然后进行选举流程。每个节点产生一个投票(myid,ZXID)(自己id,事务id)发给其他机器。

2.处理投票

每个机器与其他机器的投票信息进行对比,规则是ZXID较大的作为leader,若相等则myid较大的作为leader。然后更新自己的投票,重新发出去。

3.统计投票

服务器会统计所有投票,若有过半的机器接受到相应的投票,即选出了leader。一旦确定了leader,每个服务器会更新自己的状态,选举结束。

五、节点为什么建议奇数台

zookeeper有这样一个特性:集群中只要有过半的机器是正常工作的,那么整个集群对外就是可用的。

1.防止脑裂造成的集群不可用

若5个节点,分成2和3两个集群,zookeeper集群仍然能够选举出leader , 仍然能对外提供服务,只不过是有一部分节点失效了而已。

若6个节点,分成3和3两个集群,由于都没有过半,所以两个集群都不可用。

2.节约资源

5个节点和6个节点做多容忍挂掉的节点都是2,所以用5个就好。

六、Zookeeper与Eureka区别

著名的CAP理论指出,一个分布式系统不可能同时满足C(一致性)、A(可用性)和P(分区容错性)。由于分区容错性在是分布式系统中必须要保证的,因此我们只能在A和C之间进行权衡。在此Zookeeper保证的是CP, 而Eureka则是AP。

Zookeeper保证CP

当向注册中心查询服务列表时,我们可以容忍注册中心返回的是几分钟以前的注册信息,但不能接受服务直接down掉不可用。也就是说,服务注册功能对可用性的要求要高于一致性。但是zk会出现这样一种情况,当master节点因为网络故障与其他节点失去联系时,剩余节点会重新进行leader选举。问题在于,选举leader的时间太长,30 ~ 120s, 且选举期间整个zk集群都是不可用的,这就导致在选举期间注册服务瘫痪。在云部署的环境下,因网络问题使得zk集群失去master节点是较大概率会发生的事,虽然服务能够最终恢复,但是漫长的选举时间导致的注册长期不可用是不能容忍的。

Eureka保证AP

Eureka看明白了这一点,因此在设计时就优先保证可用性。Eureka各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而Eureka的客户端在向某个Eureka注册或时如果发现连接失败,则会自动切换至其它节点,只要有一台Eureka还在,就能保证注册服务可用(保证可用性),只不过查到的信息可能不是最新的(不保证强一致性)。除此之外,Eureka还有一种自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:

1. Eureka不再从注册列表中移除因为长时间没收到心跳而应该过期的服务

2. Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上(即保证当前节点依然可用)

3. 当网络稳定时,当前实例新的注册信息会被同步到其它节点中

因此, Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像zookeeper那样使整个注册服务瘫痪。

总结

Eureka作为单纯的服务注册中心来说要比zookeeper更加“专业”,因为注册服务更重要的是可用性,我们可以接受短期内达不到一致性的状况。不过Eureka目前1.X版本的实现是基于servlet的Java web应用,它的极限性能肯定会受到影响。期待正在开发之中的2.X版本能够从servlet中独立出来成为单独可部署执行的服务。

七、什么是脑裂

集群中的节点监听不到leader节点的心跳, 就会认为leader节点出了问题, 此时集群将分裂为不同的小集群, 这些小集群会各自选举出自己的leader节点, 导致原有的集群中出现多个leader节点。

3种可行的思路

(1) Quorums(法定人数)法:

通过设置法定人数, 进而确定集群的容忍度, 当集群中存活的节点少于法定人数, 集群将不可用。比如:

3个节点的集群中, Quorums = 2 集群可以容忍 (3 - 2 = 1) 个节点失败, 这时候还能选举出leader, 集群仍然可用。

4个节点的集群中, Quorums = 3 集群同样可以容忍 1 个节点失败, 如果2个节点失败, 那整个集群就不可用了。

(2) Redundant communications(冗余通信):

集群中采用多种通信方式, 防止一种通信方式失效导致集群中的节点无法通信。

(3) Fencing(共享资源):

通过共享资源的方式, 将所有共享资源添加到集群中, 能对共享资源进行写操作(即加锁)的节点就是leader节点。

ZooKeeper采用的方法

ZooKeeper默认采用了Quorums(法定人数)的方式: 只有获得超过半数节点的投票, 才能选举出leader。

这种方式可以确保要么选出唯一的leader, 要么选举失败。

ZooKeeper中Quorums的作用:

① 指定集群中选举leader所需的最少节点数, 保证集群可用。

② client的数据被安全保存到集群中所需的最少节点数, 一旦这些节点保存了数据, 客户端将被通知数据已经安全保存, 可以继续其他任务, 基于最终一致性, 集群中剩余的节点最终也会保存相关的数据。

ZooKeeper的写也遵循quorum机制, 因此得不到大多数支持的写是无效的。

ZooKeeper的具体解决思路

假设: leader发生了假死, followers选举出了一个新的leader。

当旧的leader复活并认为自己仍然是leader, 它向其他followers发出写请求时, 会被拒绝。

因为ZooKeeper维护了一个叫epoch的变量, 每当新leader产生时, epoch都会递增, followers如果确认了新的leader存在, 同时也会知道其epoch的值,它们会拒绝epoch小于现任leader的epoch的所有旧leader的任何请求。

注意: 仍然会存在有部分followers不知道新leader的存在, 但肯定不是大多数, 否则新leader将无法产生。

 

附录:Eureka常见问题解答

 

posted on 2020-09-30 10:48  wzyy  阅读(342)  评论(0编辑  收藏  举报