Zookeeper选举Leader源码剖析
leader选举流程
参数说明
- myid: 节点的唯一标识,手动设置
- zxid: 当前节点中最大(新)的事务id
- epoch-logic-clock: 同一轮投票过程中的逻辑时钟值相同,每投完一次值会增加
leader选举流程
- 默认投票给自己,优先选择zxid大的为leader,因为zxid大的节点数据是最新的(理论上事务id越大,说明数据量越多也就意味着比较新),如果zxid一致,那么会选择myid大的为leader,当节点选票过半则选举成功
leader选举核心步骤
-
源码大致流程
-
初始化netty通信,客户端发送命令立刻监听到
-
初始化内存数据库对象、初始化服务连接工厂等一些信息
- 启动服务节点
- 加载文件数据到内存
- 启动netty服务
- 初始化集群选举leader
- 启动一个线程进行选举监听
- 监听到选票,将选票丢到recvQueue队列中
- 启动服务节点
-
启动接收选票线程、发送选票线程进行监听,都去队列中接受和发送选票
-
启动QuorumPeer线程执行run方法,根据节点状态判断
- leading: socket监听follower节点,初始化LeaerZookeeperServer数据,同步数据到从节点,定时ping到follower节点请求保持长连接
- follower: 与leader建立发送socket连接,注册自己到leader、同步leader数据、自旋接收leader同步数据,如果leader宕了,在finally中将自己的状态改为looking,进入下一轮自旋选举
- looking: 节点启动后的默认状态,选举周期+1,初始化选票,默认选自己,发送选票到sendQueue队列,同时还会不断地从recvQueue队列拿选票进行选举
- leading: socket监听follower节点,初始化LeaerZookeeperServer数据,同步数据到从节点,定时ping到follower节点请求保持长连接
-
-
问题
: ZK的选举机制为什么存在大量自旋,如同步节点数据、选举流程,如果长时间运行会不会导致CPU资源损耗过大- 对于长时间自旋毋庸置疑肯定会导致CPU资源紧张,但是想达到动态监听数据变化就得牺牲一定的CPU性能,并且这样也能保证数据的强一致性,也能保证节点选举的实时性
- 倘若想要优化ZK,可以引入Redis/MQ基于发布/订阅模式进行处理,但是这样会造成引入三方中间件导致复杂度提升