文章目录
什么是集群脑裂?
集群的脑裂通常是发生在节点之间通信不可达的情况下,集群会分裂成不同的小集群,小集群各自选出自己的master节点,导致原有的集群出现多个master节点的情况,这就是脑裂
为什么Zookeeper一般安装为奇数个节点?
1. 防止由脑裂造成的集群不可用。
在节点数量是奇数个的情况下, zookeeper集群总能对外提供服务(即使损失了一部分节点);如果节点数量是偶数个,会存在zookeeper集群不能用的可能性(脑裂成两个均等的子集群的时候)。
2. 容错能力相同的情况下,奇数台更节省资源。
leader选举要求的可用节点数量 > 总节点数量/2;其中三个节点只允许一个节点宕机,四个节点也是只允许一个节点宕机;也就是说三个节点和四个节点的容错能力都是相同的,但是三个节点更节省资源。
Zookeeper节点必须为奇数吗?为什么?
答:不一定非得需要奇数,只需要满足可用节点数量 > 总节点数量/2就可以了,但是偶数节点的系统更加的脆弱。假设在集合中使用4个服务器, 那么多数原则对应的数量为3个服务器。 然而, 这个系统仅能容许1个服务器崩溃, 因为两个服务器崩溃就会导致系统失去多数原则的状态。 因此,在4个服务器的情况下, 我们仅能容许一个节点崩溃, 而法定人数现在却更大, 这意味着对每个请求, 我们需要更多的确认操作。
当挂掉客户端对应的zookeeper节点,客户端如何去选择其他的节点?
会话超时设置了ZooKeeper服务允许会话被声明为超时之前存在的时间。如果经过时间t之后服务接收不到这个会话的任何消息, 服务就会声明会话过期。而在客户端,如果经过t/3的时间未收到任何消息, 客户端将向服务器发送心跳消息。 在经过2t/3时间后, ZooKeeper客户端开始寻找其他的服务器, 而此时它还有t/3时间去寻找其他服务器。
Zookeeper的锁是如何实现的?
为了获得一个锁, 每个进程p尝试创建znode并指定znode为临时节点, 如果进程P成功创建了znode,就表示获得了锁并执行相应代码,其他进程监听创建的znode的变化, 并在检测到/lock删除时再次尝试创建节点来获得锁。
Zookeeper的Leader选举如何实现的?
主要从服务器初始化启动和服务运行期间无法和Leader保持连接介绍如何进行选举
服务器启动期间Leader选举
1. 每个Server发出一个投票。由于是初始情况,Server都会将自己作为Leader服务器来进行投票,每次投票会包含所推举的服务器的myid和ZXID,使用(myid, ZXID)来表示,然后各自将这个投票发给集群中其他机器。
2. 接受来自各个服务器的投票。集群的每个服务器收到投票后,首先判断该投票的有效性,如检查是否是本轮投票、是否来自LOOKING状态的服务器。
3. 处理投票。针对每一个投票,服务器都需要将别人的投票和自己的投票进行比较; 优先检查ZXID(事务ID),ZXID比较大的作为Leader;如果ZXID相同,则myid比较大的作为Leader。
4. 统计投票结果。每次投票后,服务器都会统计投票信息,判断是否已经有过半机器接受到相同的投票信息,如果超过就选举出leader。
5. 改变服务器状态。一旦确定了Leader,每个服务器就会更新自己的状态,如果是Follower,那么就变更为FOLLOWING,如果是Leader,就变更为LEADING。
服务器运行时期的Leader选举
在Zookeeper运行期间,Leader与非Leader服务器各司其职,即便当有非Leader服务器宕机或新加入,此时也不会影响Leader,但是一旦Leader服务器挂了,那么整个集群将暂停对外服务,进入新一轮Leader选举,其过程和启动时期的Leader选举过程基本一致。
1. 变更状态。Leader挂后,余下的非Observer服务器都会讲自己的服务器状态变更为LOOKING,然后开始进入Leader选举过程。
2. 每个Server会发出一个投票。在运行期间,每个服务器上的ZXID可能不同,此时假定Server1的ZXID为123,Server3的ZXID为122;在第一轮投票中,Server1和Server3都会投自己,产生投票(1, 123),(3, 122),然后各自将投票发送给集群中所有机器。
3. 接收来自各个服务器的投票。与启动时过程相同。
4. 处理投票。与启动时过程相同,此时,Server1将会成为Leader。
5. 统计投票。与启动时过程相同。
6. 改变服务器的状态。与启动时过程相同。
什么是Zookeeper的监视与通知?
替换轮询获取数据的问题,ZK选择了基于通知(notification)的机制:客户端向ZK注册需要接收通知的znode,通过对znode设置监控点(watch)来接收通知。监控点会触发一个通知。为了接收多个通知,客户端必须在每次通知后设置一个新的监控点。
Zookeeper的znode的类型
1. 临时节点(EPHEMERAL):临时创建的,会话结束节点自动被删除,也可以手动删除,临时节点不能拥有子节点
2. 临时顺序节点(EPHEMERAL_SEQUENTIAL):具有临时节点特征,但是它会有序列号,分布式锁中会用到该类型节点
3. 持久节点(PERSISTENT):创建后永久存在,除非主动删除。
4. 持久顺序节点(PERSISTENT_SEQUENTIAL):该节点创建后持久存在,相对于持久节点它会在节点名称后面自动增加一个10位数字的序列号,这个计数对于此节点的父节点是唯一,如果这个序列号大于2^32-1就会溢出。
create -s /NODE_NAME DATA # -e参数为创建临时节点,如果不带参数则创建持久节点
Zookeeper的角色都有哪些以及作用?
Leader
Leader作为整个ZooKeeper集群的主节点,负责响应所有对ZooKeeper状态变更的请求。它会将每个状态更新请求进行排序和编号,以便保证整个集群内部消息处理的FIFO。
这里补充一下ZooKeeper的请求类型。对于exists,getData,getChildren等只读请求,收到该请求的zk服务器将会在本地处理,因为由第一讲的ZAB理论可知,每个服务器看到的名字空间内容都是一致的,无所谓在哪台机器上读取数据,因此如果ZooKeeper集群的负载是读多写少,并且读请求分布得均衡的话,效率是很高的。对于create,setData,delete等有写操作的请求,则需要统一转发给leader处理,leader需要决定编号、执行操作,这个过程称为一个事务(transaction)。
Follower:
Follower的逻辑就比较简单了。除了响应本服务器上的读请求外,follower还要处理leader的提议,并在leader提交该提议时在本地也进行提交。Follower处理提议的过程已经在ZAB一章中描述过了。
另外需要注意的是,leader和follower构成ZooKeeper集群的法定人数,也就是说,只有他们才参与新leader的选举、响应leader的提议。
Observer:
如果ZooKeeper集群的读取负载很高,或者客户端多到跨机房,可以设置一些observer服务器,以提高读取的吞吐量。Observer和Follower比较相似,只有一些小区别:首先observer不属于法定人数,即不参加选举也不响应提议;其次是observer不需要将事务持久化到磁盘,一旦observer被重启,需要从leader重新同步整个名字空间。