Zab系列博客
Raft Vs Zab
//www.greatytc.com/p/24307e7ca9da
Zab系列1 核心概念
//www.greatytc.com/p/76e5dba31ea4
Zab系列2 角色和存储
//www.greatytc.com/p/d80f9250ffd1
Zab系列3 选举
//www.greatytc.com/p/0d2390c242f6
Zab系列4 zookeeper特性
//www.greatytc.com/p/08b62ca1fe4e
Zab系列5 选举恢复(源码分析)
//www.greatytc.com/p/b6acd99921b7
Zab系列6 zk单机版工作原理
//www.greatytc.com/p/ed45982b18b4
Zab系列7 集群工作原理Leader篇
//www.greatytc.com/p/59240c36ba1b
Zab系列8 集群工作原理Follower篇
//www.greatytc.com/p/8d7c7f1b2838
名词解释
electionEpoch:每执行一次leader选举,electionEpoch就会自增,用来标记leader选举的轮次。(相当于Raft系统中的term)
peerEpoch:每次leader选举完成之后,会把leader最终的electionEpoch赋值到peerEpoch。其实和electionEpoch是2个不同的值,比如在选举期间,该Node的peerEpoch不会变,而且lastCommitZxid里面的高32位也不会变,但是electionEpoch会自增1
zxid:事务请求的唯一标记,由leader服务器负责进行分配。由2部分构成,高32位是上述的peerEpoch,低32位是请求的计数,每次都从0开始。所以由zxid我们就可以知道该请求是哪个轮次的,并且是该轮次的第几个请求。
(zxid和Raft系统中的 logTerm、logIndex,不完全一样,zxid的peerEpoch和term是一个概念,但是低32位不是logIndex,低32位是从0开始递增的一个计数器。)lastProcessedZxid:最后一次commit的事务请求的zxid
(选举的时候,谁的zxid大,谁就更有机会成为leader)
(同步数据的时候,leader给follower同步数据的时候,可以根据zxid来确定要补上哪些数据)
committedLog:LinkedList<Proposal>,ZooKeeper会保存最近一段时间内执行的事务请求议案,个数限制默认为500个议案。上述committedLog就是用来保存议案的列表,上述maxCommittedLog表示最大议案的zxid,minCommittedLog表示committedLog中最小议案的zxid。
outstandingProposals(待confirm):ConcurrentMap<Long, Proposal>Leader拥有的属性,每当提出一个议案,都会将该议案存放至outstandingProposals,一旦议案被过半认同了,就要提交该议案,则从outstandingProposals中删除该议案
toBeApplied(待apply):ConcurrentLinkedQueue<Proposal> ,Leader拥有的属性,每当准备提交一个议案,就会将该议案存放至该列表中,一旦议案应用到ZooKeeper的内存树中了,然后就可以将该议案从toBeApplied中删除
Notification
数据结构
- sid 表示这个消息是谁发过来了,也就是投票人
- leader 表示投票获得者的 sid(myid)
- state:following(表示sid投票给leader,但是sid仍然没有产生leader)、leading(表示 sid 认为 leader机器 满足了leading条件)
int version;
//Proposed leader
long leader;
long zxid;
long electionEpoch;
//current state of sender
QuorumPeer.ServerState state;
//Address of sender
long sid;
QuorumVerifier qv;
long peerEpoch;
- 可能是某个Node更新了自己的投票结果,广播给别人的Notification
- 可能是某个Node广播自己已经找到了新leader,那么state=leading
- 最后都会被更新进recvset里面:
recvset.put(n.sid, new Vote(n.leader, n.zxid, n.electionEpoch, n.peerEpoch));
recvset
HashMap<Long, Vote> 用于收集LOOKING、FOLLOWING、LEADING状态下的server的投票
注意了,不仅仅是Looking状态下的投票,还有FOLLOWING、LEADING状态下的server的投票
Map<Long, Vote> recvset = new HashMap<Long, Vote>();
recvset.put(n.sid, new Vote(n.leader, n.zxid, n.electionEpoch, n.peerEpoch));
key代表是 Notification.Sender.sid,标志着这个消息是哪个节点的最新投票数据
recvset 归档set,key是vote发起方的ID,value是该发起方的最新的Vote值,因为所有Node的Vote值都是越来越新,节点只会投票给比自己当下最新的数据还新的节点投赞成票
recvset用于记录当前服务器在本轮次的Leader选举中收到的所有外部投票(按照服务队的SID区别,如{(1, vote1), (2, vote2)...})
recvset 当收到投票广播消息时,如果自己的任期小于约票的任期,就会清空recvset,因为老的recvset已经过期了,现在要PK新任期的选举投票了
outofelection
HashMap<Long, Vote>,用于收集FOLLOWING、LEADING状态下的server的投票(能够收集到这种状态下的投票,说明leader选举已经完成)
比如A节点统计投票,发现B节点在A节点上的投票满足半数,那么A进入follower状态,广播一个消息 sid=A,state=leading,leader=leaderID
比如A节点统计投票,发现A节点在A节点上的投票满足半数,那么A进入leading状态,广播一个消息 sid=A,state=leading,leader=sid
因为节点的投票结束消息,理论上不会重复投票,一个节点确认了leader之后,就会进入following状态。采用hashmap的数据结构为了实现快速的,根据sid找到投票获得者信息的方式,而不叫outofelectionSet,因为不需要过滤。
参考
ZooKeeper的一致性算法赏析
https://my.oschina.net/pingpangkuangmo/blog/778927?spm=a2c4e.11153940.blogcont62901.11.12c62ee5vwzG6o
辅助
//www.greatytc.com/p/357ca7c3b2af
zookeeper官网说明
https://zookeeper.apache.org/doc/r3.5.4-beta/zookeeperOver.html
zookeeper官网说明中文翻译版
https://blog.csdn.net/lisuo1234/article/details/55826380