ZooKeeper分布式协调框架

1. 为什么要用ZooKeeper

ZooKeeper简单易用,能够很好的解决分布式框架在运行中,出现的各种协调问题。比如集群master主备切换、节点的上下线感知等等

2. 什么是ZooKeeper?

ZooKeeper是一个分布式的,开放源码的,用于分布式应用程序的协调服务(service);是Google的Chubby的一个开源实现版
在这里插入图片描述

3. ZooKeeper应用概览

service

攘其外,安其内

简单:原语

paxos -> raft -> zab

  1. 回顾:HDFS HA方案

    ZooKeeper中三个重要的逻辑:注册、监听事件、回调函数

  • 举例类比:旅客住店流程
    在这里插入图片描述
  • NameNode + ZooKeeper

关键逻辑:注册、监听事件、回调函数
在这里插入图片描述
在这里插入图片描述

3.1 ZooKeeper之攘其外

ZooKeeper服务端有两种不同的运行模式。单机的称为"独立模式"(standalone mode);集群的称为“仲裁模式(quorum mode)”
在这里插入图片描述

  • 主从架构:Master + Slave

  • 客户端读

  • 客户端写:类比存钱
    在这里插入图片描述
    在这里插入图片描述

  • leader在通知follower执行某条命令时,如何保障每个follower都收到,并执行呢?

    队列结构

    CAP:Consistency一致性;Availability可用性;Partition Tolerance分区容错;三选二
    在这里插入图片描述

3.2 ZooKeeper之安其内

  1. 思考一下这个架构有什么问题?
    在这里插入图片描述
  • leader很重要?如果挂了怎么办?开始选举新的leader
  1. ZooKeeper服务器四种状态:
  • looking:服务器处于寻找Leader群首的状态

  • leading:服务器作为群首时的状态

  • following:服务器作为follower跟随者时的状态

  • observing:服务器作为观察者时的状态

leader选举分两种情况

  • 集群初始启动时

  • 集群运行中leader挂了时

  1. 集群启动时的Leader选举
    在这里插入图片描述
  • 以3台机器组成的ZooKeeper集群为例

  • 原则:集群中过半数Server启动后,才能选举出Leader;

  • 此处quorum数是多少?

  • 每个server投票信息vote信息结构为(sid, zxid);

    ​ server1~3初始投票信息分别为:

    ​ server1 -> (1, 0)
    ​ server2 -> (2, 0)
    ​ server3 -> (3, 0)

  • leader选举公式

    ​ server1 (zxid1, sid1)

    ​ server2 (zxid2, sid2)

    zxid大的server胜出;若zxid相等,再根据判断sid判断,sid大的胜出

  • 流程:

    • ZK1和ZK2票投给自己;ZK1的投票为(1, 0),ZK2的投票为(2, 0),并各自将投票信息分发给其他机器。

    • 处理投票。每个server将收到的投票和自己的投票对比;ZK1更新自己的投票为(2, 0),并将投票重新发送给ZK2。

    • 统计投票。server统计投票信息,是否有半数server投同一个服务器为leader;

    • 改变服务器状态。确定Leader后,各服务器更新自己的状态,Follower变为FOLLOWING;Leader变为LEADING。

    • 当K3启动时,发现已有Leader,不再选举,直接从LOOKING改为FOLLOWING。

  1. 集群运行时新leader选举

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NNz2KfOl-1598690947687)(assets/Image201906131101.png)]

3.3 难点|考点

  • 什么是仲裁quorum?

  • 为什么要仲裁?

  • quorum数如何选择? 集群节点数 / 2 + 1

  • 网络分区、脑裂

    • 网络分区:网络通信故障,集群被分成了2部分

    • 脑裂:原leader处于一个分区;另外一个分区选举出新的leader -> 2个leader

      raft算法动图地址:http://thesecretlivesofdata.com/raft/#replication

      以下以raft为例;zab与raft相似(1、zab心跳从follower到leader;2、任期叫epoch)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t5e4wFzy-1598690947687)(assets/脑裂.gif)]

在这里插入图片描述

  • 仲裁模式下,服务器数量最好为奇数个。why?
    在这里插入图片描述

4. ZooKeeper使用初体验(10分钟)

4.1 zkCli命令行

  • 启动集群(每个节点运行此命令
    在这里插入图片描述
# 启动ZooKeeper集群;在ZooKeeper集群中的每个节点执行以下命令
${ZK_HOME}/bin/zkServer.sh start
# 停止ZooKeeper集群
${ZK_HOME}/bin/zkServer.sh stop
# 查看集群状态#
${ZK_HOME}/bin/zkServer.sh status
  • 客户端连接zkServer
    在这里插入图片描述
# 使用ZooKeeper自带的脚本,连接ZooKeeper的服务器
zkCli.sh -server node-01:2181,node-02:2181,node-03:2181
  • 客户端发出读写请求
    在这里插入图片描述

ls /

create /kkb	kkb

get

set

delete

4.2 java API编程

IDE可以是eclipse,或IDEA;此处以IDEA演示

5.基本概念和操作(15分钟)

分布式通信有几种方式,1、直接通过网络连接的方式进行通信;2、通过共享存储的方式,来进行通信或数据的传输。

5.1 ZooKeeper数据结构

  • ZooKeeper所提供的服务主要是通过以下三个部分来实现的

    ZooKeeper=简版文件系统(Znode)+原语+通知机制(Watcher)。
    在这里插入图片描述

5.3 数据节点ZNode

5.3.1 什么是ZNode
在这里插入图片描述
ZNode 分为两类:持久节点、临时节点

5.3.2 持久节点

类比,文件夹

# 创建节点/zk_test,并设置数据my_data
create /zk_test my_data
# 显示的删除永久节点
delete /zk_test

5.3.3 临时节点

临时节点的生命周期跟客户端会话session绑定,一旦会话失效,临时节点被删除。

# client1上创建临时节点
create -e /tmp tmpdata

# client2上查看client1创建的临时节点
ls /

# client1断开连接
close

# client2上观察现象,发现临时节点被自动删除
ls /

5.3.4 有序节点

ZNode也可以设置为有序节点

为什么设计临时节点?

  • 创建节点时,可添加一个特殊的属性:SEQUENTIAL。

  • 一旦节点被标记上这个属性,那么在这个节点被创建时,ZooKeeper 就会自动在其节点后面追加上一个整型数字

  • 这个整数是一个由父节点维护的自增数字。

  • 提供了创建唯一名字的ZNode的方式

    # 创建持久、有序节点
    create -s /test01 test01-data
    # Created /test010000000009
    

5.4 Watcher监视与通知

5.4.1 为什么要有Watcher

问:客户端如何获取ZooKeeper服务器上的最新数据?

  • 方式一轮询:ZooKeeper以远程服务的方式,被客户端访问;客户端以轮询的方式获得znode数据,效率会比较低(代价比较大)
    在这里插入图片描述

  • 方式二基于通知的机制:客户端在znode上注册一个Watcher监视器,当znode上数据出现变化,watcher监测到此变化,通知客户端
    在这里插入图片描述

  • 对比,那种好?

5.4.2 什么是Watcher?

客户端在服务器端,注册的事件监听器;

watcher用于监听znode上的某些事件,比如znode数据修改、节点增删等;当监听到事件后,watcher会触发通知客户端

5.4.3 如何设置Watcher

注意:Watcher是一个单次触发的操作

  1. 可以设置watcher的命令如下:

Image201905291936.png

5.4.4 示例1

#ls path [watch]
#node-01 上执行
ls /zk_test watch

#node-02 上执行

create /zk_test/dir01 dir01-data

#观察node-01上变化

[zk: node-01:2181,node-02:2181,node-03:2181(CONNECTED) 87] 
WATCHER::

WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/zk_test

图示:

  • client1上执行步骤1

  • client2上执行步骤2;

  • client1上观察现象3
    在这里插入图片描述

在这里插入图片描述

5.4.5 示例2

#监控节点数据的变化;
#node2上
get /zk_test watch
#node3上
set /zk_test "junk01"
#观察node2上cli的输出,检测到变化
  1. 示例3:节点上下线监控

1)原理:

  1. 节点1(client1)创建临时节点
  2. 节点2(client2)在临时节点,注册监听器watcher
  3. 当client1与zk集群断开连接,临时节点会被删除
  4. watcher发送消息,通知client2,临时节点被删除的事件

2)用到的zk特性:

  1. Watcher+临时节点

3)好处:

  1. 通过这种方式,检测和被检测系统不需要直接关联(如client1与client2),而是通过ZK上的某个节点进行关联,大大减少了系统耦合

4)实现:

  1. client1操作

    # 创建临时节点
    create -e /zk_tmp tmp-data
    
  2. client2操作

    # 在/zk_tmp注册监听器
    ls /zk_tmp watch
    
  3. client1操作

    # 模拟节点下线
    close
    
  4. 观察client2

    WATCHER::
    
    WatchedEvent state:SyncConnected type:NodeDeleted path:/zk_tmp
    

5)图示:

client1:
在这里插入图片描述

client2:
在这里插入图片描述

5.5 会话(Session)

在这里插入图片描述

5.5.1 什么是会话

客户端与某一服务器建立TCP长连接,建立一个会话Session。

SessionTimeout

5.5.2 会话的特点

  • 客户端打开一个Session中的请求以FIFO(先进先出)的顺序执行;

  • 若打开两个Session,无法保证Session间,请求FIFO执行

5.5.3 会话的生命周期
在这里插入图片描述

5.6 请求

读写请求
在这里插入图片描述

5.7 事务zxid

增删改的操作,会形成一次事务。

ACID:原子性atomicity | 一致性consistency | 隔离性isolation | 持久性durability

每个事务有一个全局唯一的事务ID,用 ZXID 表示;

ZXID通常是一个64位的数字。由epoch+counter组成
在这里插入图片描述

6. ZooKeeper工作原理(5分钟)

ZooKeeper使用原子广播协议叫做Zab(ZooKeeper Automic Broadcast)协议

Zab协议有两种模式,它们分别是恢复模式(选主)广播模式(同步)

为了保证事务的顺序一致性,ZooKeeper采用了递增的事务id号(zxid)来标识事务,所有提议(proposal)都有zxid

6.1写操作流程图

在这里插入图片描述

  1. 在Client向Follwer发出一个写的请求
  2. Follwer把请求发送给Leader
  3. Leader接收到以后开始发起投票并通知Follwer进行投票
  4. Follwer把投票结果发送给Leader
  5. Leader将结果汇总后如果需要写入,则开始写入同时把写入操作通知给Follwer,然后commit
  6. Follwer把请求结果返回给Client

6.2 ZooKeeper状态同步

完成leader选举后,zk就进入ZooKeeper之间状态同步过程

  1. leader等待server连接;
  2. Follower连接leader,将最大的zxid发送给leader;
  3. Leader根据follower的zxid确定同步点;
  4. 完成同步后通知follower 已经成为uptodate状态;
  5. Follower收到uptodate消息后,又可以重新接受client的请求进行服务了。
    在这里插入图片描述

7. ZooKeeper典型应用案例(5分钟)

  1. NameNode使用ZooKeeper实现高可用.

  2. Yarn ResourceManager使用ZooKeeper实现高可用.

  3. 利用ZooKeeper对HBase集群做高可用配置

  4. kafka使用ZooKeeper

    • 保存消息消费信息比如offset.

    • 用于检测崩溃

    • 主题topic发现

    • 保持主题的生产和消费状态

8.编程案例

8.1 原生curd

见代码

8.2 curator编程

对ZooKeeper的api做了封装,提供简单易用的api;它的风格是curator链式编程

参考《使用curator做zk编程》

拓展点

  1. ZooKeeper常见应用场景
    在这里插入图片描述

  2. 分布式锁
    在这里插入图片描述

  3. 访问控制ACL

    参考《访问控制ACL》

六、总结(10分钟)

在这里插入图片描述

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐