七、Zookeeper原理
zab协议 的全称是 Zookeeper Atomic Broadcast (zookeeper原子广播)。zookeeper 是通过 zab协议来保证分布式事务的最终一致性
zab广播模式工作原理,通过类似两阶段提交协议的方式解决数据一致性:
-
leader从客户端收到一个写请求
-
leader生成一个新的事务并为这个事务生成一个唯一的ZXID
-
leader将这个事务提议(propose)发送给所有的follows节点
-
follower节点将收到的事务请求加入到历史队列(history queue)中,并发送ack给leader
-
当leader收到大多数follower(半数以上节点)的ack消息,leader会发送commit请求
-
当follower收到commit请求时,从历史队列中将事务请求commit
2.1、服务器状态
- looking:寻找leader状态。当服务器处于该状态时,它会认为当前集群中没有leader,因此需要进入leader选举状态。
- leading: 领导者状态。表明当前服务器角色是leader。
- following: 跟随者状态。表明当前服务器角色是follower。
- observing:观察者状态。表明当前服务器角色是observer。
2.2、服务器启动时期的leader选举
在集群初始化阶段,当有一台服务器server1启动时,其单独无法进行和完成leader选举,当第二台服务器server2启动时,此时两台机器可以相互通信,每台机器都试图找到leader,于是进入leader选举过程。选举过程如下:
-
每个server发出一个投票。由于是初始情况,server1和server2都会将自己作为leader服务器来进行投票,每次投票会包含所推举的服务器的myid和zxid,使用(myid, zxid)来表示,此时server1的投票为(1, 0),server2的投票为(2, 0),然后各自将这个投票发给集群中其他机器。
-
集群中的每台服务器接收来自集群中各个服务器的投票。
-
处理投票。针对每一个投票,服务器都需要将别人的投票和自己的投票进行pk,pk 规则如下
-
优先检查zxid。zxid比较大的服务器优先作为leader。
-
如果zxid相同,那么就比较myid。myid较大的服务器作为leader服务器。
-
对于Server1而言,它的投票是(1, 0),接收Server2的投票为(2, 0),首先会比较两者的zxid,均为0,再比较myid,此时server2的myid最大,于是更新自己的投票为(2, 0),然后重新投票,对于server2而言,其无须更新自己的投票,只是再次向集群中所有机器发出上一次投票信息即可。
-
-
统计投票。每次投票后,服务器都会统计投票信息,判断是否已经有过半机器接受到相同的投票信息,对于server1、server2而言,都统计出集群中已经有两台机器接受了(2, 0)的投票信息,此时便认为已经选出了leader
-
改变服务器状态。一旦确定了leader,每个服务器就会更新自己的状态,如果是follower,那么就变更为following,如果是leader,就变更为leading。
2.3、服务器运行时期的Leader选举
在zookeeper运行期间,leader与非leader服务器各司其职,即便当有非leader服务器宕机或新加入,此时也不会影响leader,但是一旦leader服务器挂了,那么整个集群将暂停对外服务,进入新一轮leader选举,其过程和启动时期的Leader选举过程基本一致。
假设正在运行的有server1、server2、server3三台服务器,当前leader是server2,若某一时刻leader挂了,此时便开始Leader选举。选举过程如下:
-
变更状态。leader挂后,余下的服务器都会将自己的服务器状态变更为looking,然后开始进入leader选举过程。
-
每个server会发出一个投票。在运行期间,每个服务器上的zxid可能不同,此时假定server1的zxid为122,server3的zxid为122,在第一轮投票中,server1和server3都会投自己,产生投票(1, 122),(3, 122),然后各自将投票发送给集群中所有机器。
-
接收来自各个服务器的投票。与启动时过程相同
-
处理投票。与启动时过程相同,此时,server3将会成为leader。
-
统计投票。与启动时过程相同。
-
改变服务器的状态。与启动时过程相同。
-
三、observer角色及其配置
observer角色特点:
-
不参与集群的leader选举
-
不参与集群中写数据时的ack反馈 为了使用observer角色,在任何想变成observer角色的配置文件中加入如下配置:
peerType=observer
并在所有server的配置文件中,配置成observer模式的server的那行配置追加:observer,例如:
server.3=192.168.60.130:2289:3389:observer