Observer
在Zookeeper中,除了leader和follower以外,还有一个角色是Observer。
Observer是比Follower更低级的橘色,它的功能与follower相似,可以为客户端提供查询的功能,同样把更新转移给leader。与follower不同的是,Observer不参与选主投票。所以Observer实际上是为了加强Zookeeper读的功能
如何配置Observer
只需要需要配置成Observer的节点改为如:server.3=node04:2888:3888:observer
即可
在真正生产环境中,follower更像是leader的备机,尽管它也提供读的功能。但是Observer是只为读而生。所以实际上在大集群中,应当将多数机器都配置成Observer,而只留一少部分机器作为follower
Paxos
Paxos算法有一个前提,就是说Paxos只有在一个完全可信稳定的计算环境中才成立,这个环境永不因为网络问题,黑客入侵等原因被破坏。
Paxos描述了这样一个场景,有一个叫做Paxos的小岛(Island)(zookeeper)上面住了一批居民,岛上面所有的事情由一些特殊的人决定,他们叫做议员(Senator)(server)。议员的总数(Senator Count)是确定的(在zoo.cfg中配置的server数量已经确定),不能更改。岛上每次环境事务的变更都需要通过一个提议(Proposal)(zookeeper里的事务改变),每个提议都有一个编号(PID),这个编号是一直增长的,不能倒退(zookeeper里的事务id)。每个提议都需要超过半数((Senator Count)/2 +1)的议员同意才能生效(follower选主投票机制,读写操作)。每个议员只会同意大于当前编号的提议,包括已生效的和未生效的。如果议员收到小于等于当前编号的提议,他会拒绝,并告知对方:你的提议已经有人提过了。这里的当前编号是每个议员在自己记事本上面记录的编号(记录在日志里),他不断更新这个编号(zookeeper必须处理最新的事务,不处理过期的事务)。整个议会不能保证所有议员记事本上的编号总是相同的(因为读写操作,选主等事情,只要过半的server成功通过就行)。现在议会有一个目标:保证所有的议员对于提议都能达成一致的看法。
好,现在议会开始运作,所有议员一开始记事本上面记录的编号都是0。有一个议员发了一个提议:将电费设定为1元/度。他首先看了一下记事本,嗯,当前提议编号是0,那么我的这个提议的编号就是1,于是他给所有议员发消息:1号提议,设定电费1元/度。其他议员收到消息以后查了一下记事本,哦,当前提议编号是0,这个提议可接受,于是他记录下这个提议并回复:我接受你的1号提议,同时他在记事本上记录:当前提议编号为1。发起提议的议员收到了超过半数的回复,立即给所有人发通知:1号提议生效!收到的议员会修改他的记事本,将1号提议由记录改成正式的法令,当有人问任意一个议员电费为多少时,他会查看法令并告诉对方:1元/度。(zookeeper中当更新操作给到leader之后,leader同步给所有follower,只要有超过一半的follower成功同步,就代表事务成功(之后的时间里,leader最终会将这个操作同步到follower的,称为最终一致性)
现在看冲突的解决:假设总共有三个议员S1-S3,S1和S2同时发起了一个提议:1号提议(server1和server2看到自己的事务id都是0,但是又不知道对方想有事务,所以两个人都想发提交事务id为0的事务),设定电费。S1想设为1元/度, S2想设为2元/度。结果S3先收到了S1的提议,于是他做了和前面同样的操作。紧接着他又收到了S2的提议,结果他一查记事本,咦,这个提议的编号小于等于我的当前编号1(server1的事务已生效,事务id变为1了,而server2提交的事务编号还是1),于是他拒绝了这个提议:对不起,这个提议先前提过了。于是S2的提议被拒绝,S1正式发布了提议: 1号提议生效。S2向S1或者S3打听并更新了1号法令的内容,然后他可以选择继续发起2号提议(在server1发布时,server2记事本上的事务id也变为1了,此时server2就以事务id2发出事务,这时server3就会采纳)。
但是现在会出现一个问题,就是可能因为server的数量差异,永远投票无法过半,这就导致了所有server都存活者,但是永远无法解决问题。这是Paxos提出了一个概念——总统(Leader)。只有总统有权提出提议,如果议员有自己的提议,必须发给总统并由总统来提出(这就是zookeeper中follower将更新操作交给leader完成)。
Zab(Zookeeper Atomic Broadcast)
Zab协议是Paxos算法的简化版本,只作用在有leader的状态下。
下面是Zab协议具体流程,以create操作举例,每个follewer和leader都维护一个队列进行通信传输
Watch
watch是客户端对server的一种行为,见下图
假如client1已经连接到了server,并创建了一个临时节点(ephemeral)list,现在client2也连接到了server,通过get /list获取到了list里的数据。
如果现在client1与server连接的连接断开,那么临时节点list就应该消失,可是client2如何得知这件事???
其实在使用get命令时,同时client2会对当前目录list及其子目录(如果有)进行监视,当list目录及其子目录发生变化时,就会触发事件(比如client1的连接断开就会触发list的delete事件),此时server会通过回调函数通知client2,list2已被删除。这样client2再做操作时就不会出错(如用get /list时就会发现没有该节点)
实际上也可以通过client1与client2建立心跳来通信,互相告知状态,不过这种方式时效性太慢,而zookeeper本身内部的回调机制,速度极快
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/20578.html