Zookeeper原理之数据模型, 选举机制, 监听机制, 数据一致性处理, 分布式锁应用

1. Zookeeper是什么

  • Zookeeper 是一个分布式协调服务的开源框架, 主要用来解决分布式集群中应用系统的一致性问题, 例如怎样避免同时操作同一数据造成脏读的问题.
  • ZooKeeper 本质上是一个分布式的小文件存储系统. 提供基于类似于文件系统的目录树方式的数据存储, 并且可以对树中的节点进行有效管理. 从而用来维护和监控你存储的数据的状态变化. 通过监控这些数据状态的变化,从而可以达到基于数据的集群管理.
  • 在大数据生态系统里,很多组件的命名都是某种动物,比如hadoop就是🐘,hive就是🐝。 Zookeeper的作用是用来对这些组件进行管理,即动物园管理者👮。

2. Zookeeper的数据模型

  • ZK本质上是一个分布式的小文件存储系统.
  • ZK表现为一个分层的文件系统目录树结构, 既能存储数据, 而且还能像目录一样有子节点. 每个节点可以存最多1M左右的数据.
  • 每个节点称做一个Znode, 每个Znode都可以通过其路径唯一标识.
  • 而且客户端还能给节点添加watch, 也就是监听器, 可以监听节点的变化, 这个功能常在实际开发中作为监听服务器集群机器上下线操作.

2.1 节点结构

在这里插入图片描述
图中的每个节点称为一个 Znode。 每个 Znode 由 3 部分组成:
① stat:此为状态信息, 描述该 Znode 的版本, 权限等信息
② data:与该 Znode 关联的数据
③ children:该 Znode 下的子节点

2.2 节点类型

Znode 有2大类4小类, 两大类分别为永久节点和临时节点.

  • 永久节点(Persistent): 客户端和服务器端断开连接后,创建的节点不会消失, 只有在客户端执行删除操作的时候, 他们才能被删除.
  • 临时节点(Ephemeral): 客户端和服务器端断开连接后,创建的节点会被删除.

Znode 还有一个序列化的特性, 这个序列号对于此节点的父节点来说是唯一的, 这样便会记录每个子节点创建的先后顺序. 它的格式为“%10d”(10 位数字, 没有数值的数位用 0 补充, 例如“0000000001”),因此节点可以分为4小类:

  • 永久节点(Persistent)
  • 永久_序列化节点(Persistent_Sequential)
  • 临时节点(Ephemeral)
  • 临时_序列化节点(Ephemeral_Sequential)

3. Zookeeper的watch监听机制

  • 在ZooKeeper中还支持一种watch(监听)机制, 它允许对ZooKeeper注册监听, 当监听的对象发生指定的事件的时候, ZooKeeper就会返回一个通知.
  • Watcher 分为以下三个过程:客户端向ZK服务端注册 Watcher、服务端事件发生触发 Watcher、客户端回调 Watcher 得到触发事件情况.
    触发事件种类很多,如:节点创建,节点删除,节点改变,子节点改变等。
  • Watcher是一次性的. 一旦被触发将会失效. 如果需要反复进行监听就需要反复进行注册.

3.1 监听器原理

在这里插入图片描述

  1. 首先要有一个main()线程
  2. 在main线程中创建Zookeeper客户端, 这时就会创建两个线程, 一个复制网络连接通信(connect), 一个负责监听(listener).
  3. 通过connect线程将注册的监听事件发送给zk, 常见的监听有
    • 监听节点数据的变化get path [watch]
    • 监听节点状态的变化 stat path [watch]
    • 监听子节点增减的变化 ls path [watch]
  4. 将注册的监听事件添加到zk的注册的监听器列表中
  5. zk监听到有数据或路径变化, 就会将这个消息发送给listener线程.
  6. listener线程内部调用了process()方法.此方法是程序员自定义的方法, 里面可以写明监听到事件后做如何的通知操作.

3.2 监听器实际应用

监听器+ZK临时节点能够很好的监听服务器的上线和下线.
在这里插入图片描述

  • 第一步: 先想zk集群注册一个监听器, 监听某一个节点路径
  • 第二步: 主要服务器启动, 就去zk上指定路径下创建一个临时节点.
  • 第三步: 监听器监听servers下面的子节点有没有变化, 一旦有变化, 不管新增(机器上线)还是减少(机器下线)都会马上给对应的人发送通知.

4. Zookeeper的应用场景

ZK提供的服务包括: 统一命名服务, 统一配置管理, 统一集群管理, 集群选主, 服务动态上下线, 分布式锁等.

4.1 统一命名服务

统一命名服务使用的是ZK的node节点全局唯一的这个特点.

  • 在分布式环境下,经常需要对应用/服务进行统一命名,便于识别。例如:IP不容易记住,而域名容易记住。创建一个节点后, 节点的路径就是全局唯一的, 可以作为全局名称使用.
    在这里插入图片描述

4.2 统一配置管理

统一配置管理, 使用的是Zookeeper的watch机制

  • 需求: 分布式环境下, 要求所有节点的配置信息是一致的, 比如Kafka集群. 对配置文件修改后, 希望能够快速同步到各个节点上.
  • 方案: 可以把所有的配置都放在一个配置中心, 然后各个服务分别去监听配置中心, 一旦发现里面的内容发生变化, 立即获取变化的内容, 然后更新本地配置即可.
  • 实现: 配置管理可交由Zookeeper实现
    • 可将配置信息写入Zookeeper上的一个Znode.
    • 各个客户端服务器监听这个Znode.
    • 一旦Znode中的数据被修改, Zookeeper将通知各个客户端服务器.
      在这里插入图片描述

4.3 统一集群管理

统一集群管理使用的是Zookeeper的watch机制

  • 需求: 分布式环境中, 实时掌握每个节点的状态是必要的, 可以根据节点实时状态做出一些调整.
  • 方案: Zookeeper可以实现实时监控节点状态变化
    • 可将节点信息写入Zookeeper上的一个Znode.
    • 监听这个Znode可获取它的实时状态变化.
      在这里插入图片描述

4.4 集群选主

集群选主使用的是zookeeper的临时节点.

  • 需求: 在集群中, 很多情况下是要区分主从节点的, 一般情况下主节点负责数据写入, 从节点负责数据读取, 那么问题来了, 怎么确定哪一个节点是主节点的, 当一个主节点宕机的时候, 其他从节点怎么再来选出一个主节点呢?
  • 实现:
    使用Zookeeper的临时节点可以轻松实现这一需求
    我们把上面描述的这个过程称为集群选主的过程, 首先所有的节点都认为是从节点, 都有机会称为主节点, 然后开始选主, 步骤比较简单
    1. 所有参与选主的主机都去Zookeeper上创建同一个临时节点,那么最终一定只有一个客户端请求能够 创建成功。
    2. 成功创建节点的客户端所在的机器就成为了Master,其他没有成功创建该节点的客户端,成为从节点
    3. 所有的从节点都会在主节点上注册一个子节点变更的Watcher,用于监控当前主节点
      是否存活,一旦 发现当前的主节点挂了,那么其他客户端将会重新进行选主。
      在这里插入图片描述

4.5 分布式锁

分布式锁使用的是Zookeeper的临时有序节点

  • 需求: 在分布式系统中, 很容出现多台主机操作同一资源的情况, 比如两台主机同时往一个文件中追加写入文本, 如果不去做任何的控制, 很有可能出现一个写入操作被另一个写入操作覆盖掉的状况.

  • 方案: 此时我们可以来一把锁, 哪个主机获取到了这把锁, 就执行写入, 另一台主机等待; 直到写入操作执行完毕,另一台主机再去获得锁,然后写入.
    这把锁就称为分布式锁, 也就是说:分布式锁是控制分布式系统之间同步访问共享资源的一种方式

  • 实现:

    使用Zookeeper的临时有序节点可以轻松实现这一需求.

  1. 所有需要执行操作的主机都去Zookeeper上创建一个临时有序节点.
  2. 然后获取到Zookeeper上创建出来的这些节点进行一个从小到大的排序.
  3. 判断自己创建的节点是不是最小的, 如果是, 自己就获取到了锁; 如果不是, 则对最小的节点注册一个监听.
  4. 如果自己获取到了锁, 就去执行相应的操作. 当执行完毕之后, 连接断开, 节点消失, 锁就被释放了.
  5. 如果自己没有获取到锁, 就等待, 一直监听节点是否消失,锁被释放后, 再重新执行抢夺锁的操作.
    在这里插入图片描述

5. Zookeeper集群[高级]

5.1 ZK集群介绍

Zookeeper在一个系统中一般会充当一个很重要的角色, 所以一定要保证它的高可用, 这就需要部署Zookeeper的集群. Zookeeper 有三种运行模式: 单机模式, 集群模式和伪集群模式.

  • 单机模式: 使用一台主机不是一个Zookeeper来对外提供服务, 有单点故障问题, 仅适合于开发、测试环境.
  • 集群模式: 使用多台服务器, 每台上部署一个Zookeeper一起对外提供服务, 适合于生产环境.
  • 伪集群模式: 在服务器不够多的情况下, 也可以考虑在一台服务器上部署多个Zookeeper来对外提供服务.

5.2 Zookeeper集群的特点

1)Zookeeper: 一个领导者(Leader), 多个跟随者(Follower)组成的集群.
2)集群中只要有半数以上节点存活, Zookeeper集群就能正常服务.
3)全局数据一致: 每个Server保存一份相同的数据副本, Client无论连接到哪个Server, 数据都是一致的.
4)更新请求顺序性: 从同一个客户端发起的事务请求,最终会严格按照顺序被应用到zookeeper中.
5)数据更新原子性: 一次数据更新要么成功, 要么失败。
6)实时性,在一定时间范围内,Client能读到最新数据。

5.3 数据一致性处理

ZK是一个分布式协调开源框架, 用于分布式系统中保证数据一致性问题, 那么ZK是如何保证数据一致性的呢?

5.3.1 集群角色

  • Leader: 负责投票的发起和决议, 更新系统状态, 是事务请求(写请求) 的唯一处理者, 一个ZooKeeper同一时刻只会有一个Leader.
    对于create创建/setData修改/delete删除等有写操作的请求, 则需要统一转发给leader 处理, leader 需要决定编号和执行操作, 这个过程称为一个事务.
  • Follower: 接收客户端请求, 参与选主投票. 处理客户端非事务(读操作)请求,转发事务请求(写请求)给 Leader;
  • Observer: 针对访问量比较大的 zookeeper 集群, 为了增加并发的读请求. 还可新增观察者角色.
    作用: 可以接受客户端请求, 把请求转发给leader, 不参与投票, 只同步leader的状态.
    ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210120101239906.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjY0MTkwOQ==,size_16,color_FFFFFF,t_70

5.3.2 ZAB协议

  • Zookeeper采用ZAB(Zookeeper Atomic Broadcast)协议来保证 分布式数据一致性
  • ZAB并不是一种通用的分布式一致性算法,而是一种专为Zookeeper设计的崩溃可恢复的原子消息广播算法
  • ZAB协议包括两种基本模式: 崩溃恢复 模式和 消息广播 模式:
    • 消息广播模式主要用来进行事务请求的处理
    • 崩溃恢复模式主要用来在集群启动过程,或者Leader服务器崩溃退出后进行新的Leader服务器的选举以及数据同步.

5.3.3 ZK集群写数据流程

在这里插入图片描述

  • Client向Zookeeper的Server1上写数据, 发送一个写请求.
  • 如果Server1不是Leader, 那么Server1会把接受的请求进一步转发给Leader, 因为每个Zookeeper的Server里面有一个是Leader. 这个Leader会将写请求广播给各个Server, 比如Server1和Server2, 各个Server会将该写请求加入待写队列, 并向Leader发送成功信息(ack反馈机制).
  • 当Leader收到半数以上Server的成功信息, 说明该写操作可以执行. Leader会向各个Server发送事务提交信息, 各个Server收到信息后会落实队列里面的写请求, 此时写成功.
  • Server1会进一步通知Client数据写成功了, 这是就认为整个写操纵成功.

5.4 ZK集群选举机制

Zookeeper服务器有四个状态:
looking: 寻找leader状态, 当服务器处于该状态时, 它会认为当前集群中没有leader, 因此需要进入leader选举状态.
leading: 领导者状态, 表明当前服务器角色是leader.
following: 跟随者状态, 表明当前服务器角色是follower.
observing:观察者状态, 表明当前服务器角色是observer。

  • 半数机制: 集群中半数以上机器存活, 集群可用, 所以Zookeeper适合安装奇数台服务器. 集群启动时, 如果当前机器票数超过了总票数一半则为Leader, Leader产生后, 投过票的机器就不能再投票了.
  • Zookeeper虽然在配置文件中没有指定主从节点. 但是, Zookeeper工作时, 是有一个节点Leader, 其他则为Follower, Leader是通过内部的选举机制临时产生的.
    配置文件中会指定每台ZK的myid, 而且不能重复, 通常用1,2,3…区分每台ZK的myid.

5.4.1 集群启动器的选举机制

在集群初始化阶段, 当有一台服务器server1启动时, 其单独无法进行和完成leader选举, 当第二台服务器server2启动时, 此时两台机器可以相互通信, 每台机器都试图找到leader, 于是进入leader选举过程.
在这里插入图片描述

  1. 服务器 1 启动, 服务器 1 状态保持为looking.
  2. 服务器 2 启动, 发起一次选举. 服务器 1 投票给比自己ID号大的服务器2. 服务器2投票给自己.
    投票结果: 服务器 1 票数 0 票, 服务器 2 票数 2 票, 没有半数以上结果, 选举无法完成, 服务器 1, 2 状态保持looking.
  3. 服务器 3 启动, 发起一次选举. 此时服务器 1 和 2 都会更改选票为服务器 3, 服务器3投票给自己.
    投票结果: 服务器 1 为 0 票, 服务器 2 为 0 票, 服务器 3 为 3 票. 此时服务器 3 的票数已经超过半数,服务器 3 当选 Leader. 服务器 1,2 更改状态为follower,服务器 3 更改状态为leader;
  4. 服务器 4 启动, 发起一次选举. 此时服务器 1,2,3 已经不是looking状态, 不会更改选票信息, 服务器4投票给自己.
    投票结果:服务器 3 为 3 票,服务器 4 为 1 票。此时服务器 4服从多数,更改选票信息为服务器 3,并更改状态为 following;
  5. 服务器 5 启动,同 4 一样当小弟.

5.4.2 服务器运行时期的Leader选举

在zk运行期间, leader与非leader服务器各司其职, 即便当有非leader服务器宕机或者新加入, 此时也不会影响leader. 但是一旦leader服务器宕机了, 那么整个集群将会暂停对外服务, 进入新一轮leader选 举, 其过程和启动时期的Leader选举过程基本一致.

假设正在运行的有server1,server2,server3三台服务器,当前leader是server2,若某一时刻leader挂了, 此时便开始leader选举. 选举过程如下:

  • 变更转态, server1和server3变更为looking状态.
  • 开始投票, 每台服务器投票给比自己myid大的机器, 没有比自己大的就投给自己.
  • 这样server3有2票, server1有1票, server3的票数超过了集群一半, 当选leader, server1变更状态follower.

6. 为什么zookeeper集群的数目,一般为奇数个

6.1 容错

由于在增删改操作中需要半数以上服务器通过,来分析以下情况。

  • 2台服务器,至少2台正常运行才行(2的半数为1,半数以上最少为2),正常运行1台服务器都不允许挂掉
  • 3台服务器,至少2台正常运行才行(3的半数为1.5,半数以上最少为2),正常运行可以允许1台服务器挂掉
  • 4台服务器,至少3台正常运行才行(4的半数为2,半数以上最少为3),正常运行可以允许1台服务器挂掉
  • 5台服务器,至少3台正常运行才行(5的半数为2.5,半数以上最少为3),正常运行可以允许2台服务器挂掉
  • 6台服务器,至少3台正常运行才行(6的半数为3,半数以上最少为4),正常运行可以允许2台服务器挂掉

通过以上可以发现,3台服务器和4台服务器都最多允许1台服务器挂掉,5台服务器和6台服务器都最多允许2台服务器挂掉
但是明显4台服务器成本高于3台服务器成本,6台服务器成本高于5服务器成本。这是由于半数以上投票通过决定的。

6.2 防脑裂

6.2 什么是脑裂

于假死会发起新的leader选举, 选举出一个新的leader, 但旧的leader网络又通了. 导致出现了两个leader , 有的客户端连接到老的leader,而有的客户端则连接到新的leader.

6.2 zookeeper脑裂是什么原因导致的?

由于集群部署于多个机房, 机房和机房之间偶尔出现网络延迟, 导致一个集群成为两个集群. 虽然是很短时间, 有可能在这短时间内客户端发现少了一部分机器, 另一部分机器则会重新选举leader, 这样就出现脑力了, 就是一个集群两个大脑.

6.3 奇数台可以防脑裂

  • 如果是6台机器, 两个机房, 正常情况下,此集群只会有一个Leader.
    在这里插入图片描述
  • 那么如果机房之间的网络断了之后,那么就会出现每个机房内部都将选出一个Leader, 这就是脑裂现象, 一个集群两个大脑.
    在这里插入图片描述
  • 如果是部署了5台机器, 两个机房, 那么就算网络中断了, 由于有半数机制, 也就是投票超过半数以上才能选出leader, 那么另一个机房就不会出现leader.
    在这里插入图片描述
  • 因此总结得出, 有了过半机制, 对于一个Zookeeper集群来说, 要么没有Leader, 要么只有1个Leader, 这样zookeeper也就能避免了脑裂问题, 因此ZK适合部署奇数台服务器.
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值