• ZooKeeper 5:集群模式


    prev:ZooKeeper 4:会话处理与其源码分析

    ZooKeeper作为目前开源技术体系的无可替代的基础组件,首先要保证自身的高可用,也就是对于部分服务下线要有一定的容忍能力,不能说ZooKeeper突然挂了所有的服务都跟着寄了。
    为保证高可用,ZooKeeper提供了集群模式,或者说是Master/Slave架构,防止单点故障影响整个服务。

    角色与职责

    在这里插入图片描述
    图源:ZooKeeper 集群

    角色职责
    Leader可以处理读写请求这里的读写请求来自Follower和Observer;事务的发起和决议;更新系统状态
    Follower处理读请求,将写请求转发给Leader;参与Leader发起的事务处理,负责本节点的数据变更和事务提交;参与Leader选举;同步Leader状态(保持心跳连接)
    Observer处理读请求,将写请求转发给Leader ;不参与Leader发起的事务处理;不参与Leader选举 ;同步Leader状态(保持心跳连接)

    为什么要引入Observer(ZK 3.3.0)?

    1. 在不影响写性能的前提下,提升读操作的性能和吞吐量
      ① Follower数量越多,写操作的性能越差,吞吐量越小
      ② Observer不参与事务处理,数量再多也不影响集群的写性能
      ③ Observer不参与选主和事务处理,即使宕机也不影响集群的可用性
    2. 提升集群的可扩展性,以及大规模访问的承载能力
    3. 跨中心部署Observer ,为本地读请求提供快速响应
      ① Leader和Follower部署在一个中心,很大程度上降低了网络延时对写性能的影响
      ②由于Observer要转发写请求和同步Leader状态,所以跨中心部署并不能彻底消除网络延时
      例如:阿里开源的跨机房同步系统Otter

    仲裁机制

    Leader和Follower遵循Quorum仲裁机制(过半策略),也就是说,若Leader+Follwer的数量为m,则Quorum = m/2 + 1,只有投票数大于等于Quorum,事务和选举才判定成功。
    因此官方文档强烈建议使用奇数台服务器作为ZooKeeper集群,这样的话在不影响事务处理的前提下,最多可容忍n台宕机。
    举个例子:
    对于节点数为5和6的两个集群:

    • 二者都最多容忍2台宕机,所以容灾能力相同;
    • 前者的Quorum数为3,后者为4,前者更小,事务处理和选举的效率更高

    为什么采用过半策略

    防止集群脑裂:对于一个集群,通常多台机器会部署在不同机房,来提高这个集群的可用性。保证可用性的同时,会发生一种机房间网络线路故障,导致机房间网络不通,而集群被割裂成几个小集群。这时候子集群各自选主导致“脑裂”的情况,会导致数据一致性问题。ZooKeeper的过半机制导致不可能产生 2 个leader,因为少于等于一半是不可能产生leader的,这就使得不论机房的机器如何分配都不可能发生脑裂。

    状态和选举

    服务器的四种状态:

    • LOOKING:寻找Leader状态,表示当前集群没有Leader,需要进行选举
    • LEADING:领导者状态,当前角色为Leader
    • FOLLOWING:跟随者状态,Leader选举已完成,当前角色为Follower
    • OBSERVING:观察者状态,当前角色为Observer,不参与选举和写事务

    选举的原则:选择能力强,数据新的节点作为Leader

    选票

    选票的数据结构:(sid, zxid),sid为服务器id,zxid为当前服务器的最大事务id
    选票的比较规则: ①zxid大的胜出;②若zxid相等,则sid大的胜出

    从选票也可以看出,zxid代表了这个机器上的ZooKeeper服务是不是最新的,否则要看机器id的大小了。

    启动期间的Leader选举

    在这里插入图片描述
    如上图所示,在启动时期Leader选举

    1. 启动ZK1并发起投票。投票(1,0)给自己,发现未过半数,选不出Leader
    2. 启动ZK2
      (1)发起第1轮投票。ZK1和ZK2分别投票给自己和其他服务器,ZK1为(1,0),ZK2为(2,0)
      (2)统计第1轮投票。ZK1对投给自己的票(1,0)与ZK2发过来的票(2,0)进行比较,根据比较规则,(2,0)胜出,ZK1更新自己的投票为(2,0);以此类推,ZK2保持自己的投票(2,0)不变。至此,ZK1和ZK2都给ZK2投了1票,但未过半数,选不出Leader
      (1)发起第2轮投票。 ZK1和ZK2分别投票给自己和其他服务器,ZK1为(2,0),ZK2为(2,0)
      (2)统计第2轮投票。 ZK1和ZK2都有2票(2,0),已超过半数,ZK2当选Leader
      (3)更改Server状态。将ZK2的状态改为LEADING,ZK1的状态改为FOLLOWING
    3. 启动ZK3。发现已有Leader,不再选举,直接从LOOKING改为FOLLOWING

    运行期间的Leader选举

    在这里插入图片描述
    这里也贯穿着选举思想:能力强,数据新
    如上图所示:

    1. 某时刻,之前的Leader ZK2挂了,此时需要一台新的Leader,ZK1和ZK3的状态为Looking
    2. 第一轮投票
      (1)发起第1轮投票。ZK1和ZK3分别投票给自己和其他服务器,ZK1为(1,124),ZK3为(3,123)
      (2)统计第1轮投票。ZK1对投给自己的票(1,124)与ZK2发过来的票(3,123)进行比较,根据比较规则,(1,124)胜出,因为ZK1上的数据事务id大,说明数据比较新,ZK3更新自己的投票为(1,124);以此类推,ZK1保持自己的投票(1,124)不变。至此,ZK1和ZK3都给ZK2投了1票,但未过半数,选不出Leader
    3. 第二轮投票
      (1)发起第2轮投票。 ZK1和ZK3别投票给自己和其他服务器,ZK1为(1,124),ZK3为(1,124)
      (2)统计第2轮投票。 ZK1和ZK3都统计到有2票(1,124),已超过半数,ZK1当选Leader
      (3)更改Server状态。将ZK1的状态改为LEADING,ZK3的状态改为FOLLOWING

    配置集群模式

    环境:Mac,ZooKeeper3.8
    仍然继续第一部分的安装。
    首先复制出来三个ZooKeeper的目录,分别命名为:zookeeper-01,zookeeper-02,zookeeper-03
    修改配置文件/conf/zoo.cfg

    # zk1
    dataDir=/usr/local/software/zookeeper-01/data
    dataLogDir=/usr/local/software/zookeeper-01/log
    clientPort=2181
    server.1=127.0.0.1:2887:3887
    server.2=127.0.0.1:2888:3888
    server.3=127.0.0.1:2889:3889
    # zk2
    dataDir=/usr/local/software/zookeeper-02/data
    dataLogDir=/usr/local/software/zookeeper-02/log
    clientPort=2182
    server.1=127.0.0.1:2887:3887
    server.2=127.0.0.1:2888:3888
    server.3=127.0.0.1:2889:3889
    # zk3
    dataDir=/usr/local/software/zookeeper-03/data
    dataLogDir=/usr/local/software/zookeeper-03/log
    clientPort=2183
    server.1=127.0.0.1:2887:3887
    server.2=127.0.0.1:2888:3888
    server.3=127.0.0.1:2889:3889
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    在data下创建myid文件并写入1,2,3:

    # zk1
    vim data/myid
    # 输入1,wq
    # zk2
    vim data/myid
    # 输入2,wq
    # zk3
    vim data/myid
    # 输入3,wq
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    运行:

    /zookeeper-01/bin/zkServer.sh start
    /zookeeper-01/bin/zkServer.sh start
    /zookeeper-01/bin/zkServer.sh start
    
    • 1
    • 2
    • 3

    检查服务状态:

    /zookeeper-01/bin/zkServer.sh status
    Using config: /usr/local/software/zookeeper-01/bin/../conf/zoo.cfg
    Client port found: 2181. Client address: localhost. Client SSL: false.
    Mode: follower
    
    /zookeeper-02/bin/zkServer.sh status
    ZooKeeper JMX enabled by default
    Using config: /usr/local/software/zookeeper-02/bin/../conf/zoo.cfg
    Client port found: 2182. Client address: localhost. Client SSL: false.
    Mode: follower
    
    /zookeeper-03/bin/zkServer.sh status
    ZooKeeper JMX enabled by default
    Using config: /usr/local/software/zookeeper-03/bin/../conf/zoo.cfg
    Client port found: 2183. Client address: localhost. Client SSL: false.
    Mode: leader
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    参考

    ZooKeeper在Mac上集群部署
    ZooKeeper 集群
    大数据理论与实践2 分布式协调服务Zookeeper

  • 相关阅读:
    linux的常用命令及常用工具安装
    【接口测试】Day7-接口测试框架
    SpringBoot-SpringCache缓存
    Android热修复Sophix的使用
    【计算机视觉40例】案例15:KNN数字识别
    R语言使用plot函数可视化数据散点图,使用xlab参数自定义设置X轴的轴标签
    搞定!详解MeterSphere 配置外部Mysql5.7的全过程
    【yolov8系列】yolov8的目标检测、实例分割、关节点估计的原理解析
    2023年【北京市安全员-B证】考试试卷及北京市安全员-B证模拟考试题
    【消息队列笔记】chp4-如何处理消费时的重复消息
  • 原文地址:https://blog.csdn.net/mxb1234567/article/details/125504026