Zookeeper基础概念及相关原理

分布式协调服务

一、Zookeeper使用场景

适合读多写少的场景

  1. 统一命名服务

  2. 统一配置管理

  3. 分布式集群管理(注册中心)

  4. 分布式锁

  5. 负载均衡

二、 Zookeeper内部结构

zookeeper节点
类似于Unix文件系统

每个子目录项(路径) 都被称作为znode,和文件系统一样,我们能够自由的增加、删除znode,在一个znode下增加、删除子znode,唯一的不同在于znode是可以存储数据的。

ZooKeeper数据模型中的每个znode都维护着一个stat结构,提供元数据,它由版本号,操作控制列表(ACL),时间戳和数据长度组成。

  • 版本号 每当与znode相关联的数据发生变化时,其对应的版本号也会增加

  • 操作控制列表(ACL) ACL基本上是访问znode的认证机制。它管理所有znode读取和写入操作

  • 时间戳 时间戳表示创建和修改znode所经过的时间,ZooKeeper从“事务ID"(zxid)标识znode的每个更改

  • 数据长度 最多存储1M数据

节点类型

  • 持久化有序
  • 持久化无序
  • 临时有序节点
  • 临时无序节点

三、Zookeeper提供的原语服务

  • create /path data:创建一个名为/path的znode节点,并包含data数据(不包含创建失败)
  • delete /path:删除名为/path的znode
  • exists /path:检查是否存在名为/path的节点
  • setData /path data:设置名为/path的znode的数据为data
  • getData /path:返回名为/path节点的数据
  • getChildren /path:返回/path节点的子节点列表

四、Zookeeper分布式锁

思路:

  1. 客户端client_1尝试获取锁,调用create()方法在locker节点下创建临时顺序节点node_1
  2. 客户端调用getChildren("/locker")来获取locker节点下所有字节点,同时在这个节点上注册上子节点变更通知的Watcher
  3. 如果发现自己在步骤1中创建的节点是所有节点中序号最小的,那么就认为这个客户端获得了锁
  4. 在步骤3中发现自己并非是所有子节点中最小的,说明自己还没有获取到锁,就开始等待,直到下次子节点变更通知的时候,再进行子节点的获取,判断是否获取锁
  5. 释放锁就是删除自己创建的那个子节点即可

上面的过程有问题:
首先在分布式锁中,会有很多客户端来尝试获取锁,他们在判断自己节点获取的结果都是自己不是最小节点,在最小节点被删除时,客户端会受到大量无效通知——羊群效应
我们的关注点是:每个节点只关注比自己序号小的那个节点的状态。

改进分布式锁:

  1. 客户端client_1尝试获取锁,调用create()方法在locker节点下创建临时顺序节点node_1

  2. 客户端调用getChildren("/locker")来获取locker节点下所有字节点,这里向比它靠前节点注册Watcher;

  3. 如果发现自己在步骤1中创建的节点是所有节点中序号最小的,那么就认为这个客户端获得了锁

  4. 在步骤3中发现自己并非是所有子节点中最小的,说明自己还没有获取到锁,就开始等待,直到下次子节点变更通知的时候,再进行子节点的获取,判断是否获取锁

  5. 最终会形成Client_1得到了锁,Client_2监听了node1,Client_3监听了node2,形成一个等待队列,有点类似AQS

  6. 释放锁就是删除自己创建的那个子节点即可,并且只有相邻节点会收到通知,判断自己是不是最小,获取锁。

Zookeeper作为分布式锁非常容易实现,但是增删节点效率偏低。

五、Zookeeper分布式集群

1. Zookeeper的角色:

  • 领导者(Leader),负责进行投票的发起和决议,更新系统状态
  • 学习者(Learner),包括跟随者(Follower)和观察者(observer):
    Follower用于接受客户端请求并想客户端返回结果,在选主过程中参与投票,Observer可以接受客户端连接,将写请求转发给Leader,但observer不参加投票过程,只同步Leader的状态,observer的目的是为了扩展系统,提高读取速度
2. Zookeeper下Server的工作状态

Looking :选举状态
Following :Leader已经选举产生,当前Server与之同步
Leading :主节点所处的状态

3. Zookeeper工作原理

Zookeeper核心:原子广播,通过Zab协议实现
ZAB协议两种模式:消息广播和崩溃恢复

消息广播:

  1. 在Client向Follwer发出一个写的请求

  2. Follwer把请求发送转发给Leader

  3. Leader接收到以后开始发起投票并通知Follwer进行投票, 注:Observer不参与

  4. Follwer把投票结果发送给Leader

  5. Leader将结果汇总,广播通知所有Follower写入数据,

  6. Follower写入完成后,同时把写入操作通过ACK消息通知给Leader,Leader收到半数以上成功ACK(这里会造成Zookeeper读数据的时候,数据不一致,半数以上为新数据,半数以下存在老数据,所以在读数据是需要调用sync()同步方法),进行commit,并进行广播;
    注:对于zookeeper来说,它实现了A可用性、P分区容错性、C中的写入强一致性,丧失的是C中的读取一致性

  7. Follwer把请求结果返回给Client

Zookeeper为保持事务的顺序性,采用递增的zxid标识每个每个提议,zxid是64位数字,高32位epoch标识Leader状态,就是Leader统治状态,每次选出新的Leader同时就会产生新的epoch,低32位用来自增。

Zookeeper选主过程:

Zookeeper第一次进行选主过程:

Zookeeper集群有5个Server
投票过程:server1连入Zookeeper,投票给自己,成为Leader,Server2连入,投票给自己和Server1,发现Server2的zxid较新,Server2当选成为新Leader
Server3连入,重复上面过程,成为Leader,这时有超过半数以上Server投票给Server3,Server3当选成为Leader,Server4,5连入,就算zxid最新,也不会当选成为Leader。

崩溃恢复:
这个过程很复杂,以下是个人理解: Zookeeper选举算法有两种模式:

  • Basic Paxos
  • Fast Paxos
    默认使用Fast Paxos.

选举过程:

  1. 选举线程由当前Server发起选举的线程担任,主要功能是对投票结果进行统计,并选出推荐的Server

  2. 选举阶段,所有集群的节点处于Looking状态,它们会向其它节点发起投票,投票内容包含(服务器ID, zxid).

  3. 该节点同时会收到其它节点的投票,它会将自身zxid和其它zxid比较,选择最新的zxid,重新发起投票.

  4. 发起选举的线程统计票数,判断过半获得投票的节点,并将它设置为Leader,状态变为Leading,其它节点状态变为Following

  5. 这个时候,如果上一个Leader并不是挂掉,而是因为网络问题,通信延迟,现在恢复通信,就会因为两个Leader产生脑裂情况.
    所以进入发现阶段:
    Leader会收集所有Follwer的Zxid,Leader会选出最大Zxid,基于zxid的epoch加1,,再将这个生成的zxid广播给所有的Follower,各个Follower收到全新的zxid后,返回ACK给Leader,带上各自最大的zxid和历史事务日志,Leader选出最大的zxid,并更新自身历史日志,这种情况就可以避免脑裂

  6. Leader将最新的事务日志,同步给所有Follower,当半数Follower同步成功,这个Leader就开始了自己的统治时代

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值