ZookeeperA. zookeeper 的由来- 由于大数据的发展,分布式集群之间的关系变得非常复杂
- 例如 NameNode 的 HA,我们搭建 2 台 NameNode 支持 HA,但是遇到问题 : 到底客户端访问哪一台 NameNode
- 于是把 NameNode1 和 NameNode2 统称为 NameSpace
- 客户端连接到 NameSpace ,NameSpace 的节点保存在 zookeeper 上
- 在 NameSpace 中只有 1 台 NameNode 真正干活
- zookeeper 就是分布式的协调服务
B. zookeeper 概述- zookeeper 是一个开源的分布式协调服务
- ZooKeeper 是一个典型的分布式数据一致性解决方案
- 分布式应用程序可以基于 ZooKeeper 实现
- 诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master 选举、分布式锁和分布式队列等功能
- Zookeeper 提供的服务功能有
C. dubbo 框架介绍- Zookeeper 一个最常用的使用场景就是用于担任服务生产者和服务消费者的注册中心
- 服务生产者将自己提供的服务注册到 Zookeeper 中心
- 服务的消费者在进行服务调用的时候先到 Zookeeper 中查找服务
- 获取到服务生产者的详细信息之后,再去调用服务生产者的内容与数据
D. zookeeper 基础概念- zookeeper 在搭建的时候,建议使用奇数台(避免浪费)
- zookeeper 也是一个高可用的集群(允许最多挂多少台)
- 集群中节点的数量只要存活的节点数量大于总节点数的半数就可以运行
- zookeeper 为了保证数据的一致性,在节点中选举 leader 来进行数据的读写
- follow 从 leader 中进行数据同步
- follow 参与选举 leader
E. zookeeper 重要概念- ZooKeeper 本身就是一个分布式程序
- 只要半数以上节点存活,ZooKeeper 就能正常服务
- 为了保证高可用,最好是以集群形态来部署 ZooKeeper
- 这样只要集群中大部分机器是可用的,那么ZooKeeper 本身仍然是可用的
- ZooKeeper 将数据保存在内存中,保证了高吞吐量和低延迟
- 但是内存限制了能够存储的容量不太大,此限制也是保持 znode 中存储的数据量较小的进一步原因
- ZooKeeper 是高性能的
- 在“读”多于“写”的应用程序中尤其地高性能
- 因为“写”会导致所有的服务器间同步状态
- Zookeeper 存储数据以 key-value 形式存储
- 但是 key 类型比较特殊,类似路径的形式"/keyname/aa/bb", 我们称之为 znode
- value 值可以是任意的二进制数据 byte[]
F. zookeeper 节点类型- ZNode 由两部分组成
- 节点的名称 : 路径
- 节点的数据 : byte[] 数据
- ZNode 节点类型
- 永久节点(persistent)
- 临时节点(ephemeral)
- 创建节点的客户端与 zookeeper server 失去连接,该节点就会消失
- 顺序节点(sequential)
- 衍生类型
ZNode 节点创建实战[AppleScript] 纯文本查看 复制代码 bin/zkCli.sh -server host:port cmd args
- A. 创建节点
- 查看根节点下的 ZNode 节点
[AppleScript] 纯文本查看 复制代码 zk: ls /
创建 ZNode 节点类型 [AppleScript] 纯文本查看 复制代码 # 创建永久节点
zk: create /doit 51do.cn
# 创建顺序节点
zk: create -s /doit/oldsheep laoyang
# 节点名会加上顺序编号
# 创建临时节点
zk: create -e /doit/xiaohei heiheihei
# 在其他节点闪也可以看到,当创建它的客户端下线后就会消失
# 用 close 关闭客户端
B. 获取节点数据
[AppleScript] 纯文本查看 复制代码 zk: get 节点路径
C. 更改节点数据[AppleScript] 纯文本查看 复制代码 zk: set 节点路径 value
D. ZNode 节点版本- zookeeper 为每一个 ZNode 节点维护着一个叫做 stat 的数据结构
- 在 stat 中维护了节点相关的 3 个版本
- 当前 ZNode 的版本 dataVersion
- 当前 ZNode 子节点的版本 cversion
- 当前 ZNode 的 ACL(Access Control List)版本 aclversion
E. 状态信息- 每个 ZNode 除了存储数据内容之外,还存储了 ZNode 本身的一些状态信息
- 用 get 命令可以同时获得某个 ZNode 的内容和状态信息
- cZxid : 表示 Znode 被创建时的事务 ID
[AppleScript] 纯文本查看 复制代码 [zk: localhost:2181(CONNECTED) 1] get /brokers/ids/0
{"listener_security_protocol_map":{"PLAINTEXT":"PLAINTEXT"},"endpoints":["PLAINTEXT://10.172.50.11:9092"],"jmx_port":-1,"ho
st":"10.172.50.11","timestamp":"1539155719044","port":9092,"version":4}
cZxid = 0x600000159 // 表示 Znode 被创建时的事务 ID
ctime = Wed Oct 10 15:15:19 CST 2018 // Znode 被创建的时间
mZxid = 0x600000159 // 表示 Znode 最后一次被更新时的事务 ID
mtime = Wed Oct 10 15:15:19 CST 2018 // 表示改节点最后一次被更新的时间
pZxid = 0x600000159 // 表示该节点子节点列表最后一次被修改时的事务 ID.注意,只有子节点列表变更了才会变更 pZxid
cversion = 0 // 子节点的版本号
dataVersion = 0 // 数据节点的版本号
aclVersion = 0 // ACL 版本号
ephemeralOwner = 0x10000032ae90001 //创建该节点的会话的 seddionID。如果该节点是持久节点,那么这个属性值为 0
dataLength = 194 //数据内容的长度
numChildren = 0 //子节点的个数
F. 事务操作- 在 zookeeper 中,能改变 zookeeper 服务器状态的操作称为【事务操作】
- 一般包括数据节点创建与修改,数据内容更新和客户端会话创建与失效等操作
- 对于客户端的每一个更新请求,zookeeper 都会分配一个全局唯一的递增编号,这个编号反映了所有事务操作的先后顺序
- 应用程序可以使用 zookeeper 这个特性来实现更高层次的同步原话
- 这个编号也叫做时间戳——zxid【zookeeper transaction Id】
- zxid 通常是一个64位的数字
- 这个数字分为高32位和低32位
- 高32位是选举leader的纪元编号
- 低32位是事务编号
F. watcher(事件监听器)- Watcher 是 zookeeper 中的一个很重要的特性
- zookeeper 允许用户在指定节点上注册一些 watcher
- 并且在一些特定时间触发的时候,zookeeper 服务端会将事件同传到感兴趣的客户端去
- 该机制是 zookeeper 实现分布式协调服务的重要特性
- zookeeper 的监听分为 2 种
- 节点数据变化的监听
- 节点下子节点变化的监听
- 只能监控节点的儿子节点,不能监控其儿子节点之外的节点事件
G. ZAB协议- ZAB(zookeeper atomic broadcast 原子广播)协议是为分布式协调服务 zookeeper 专门设计的一种支持崩溃恢复的原子广播协议
- 在 zookeeper 中,主要依赖 ZAB 协议来实现分布式数据一致性
- 基于该协议,zookeeper 实现了一种主备模式的系统架构来保持集群中各个副本之间的数据一致性
- ZAB 协议有两种模式,阀门分别为【恢复模式(选主)】和【广播模式(同步)】
- 当服务启动或者 leader 崩溃后,ZAB 就进入了恢复模式
- 当 leader 被选举出来, 且大多数 server 完成了和 leader 的状态同步以后,恢复模式就结束
- 状态同步保证了 leader 和 server 具有相同的而系统状态
- zookeeper 的 ZAB 协议实现数据一致性具体表现形式就是通过 ZXID
H. zookeeper 如何保证数据的一致性- 因为 zookeeper 中有事务,事务是由 zab 协议实现的
- zab 协议体现在 zxid 上,zxid 是一个 64 位的数据
- 这个数字分为高 32 位 和 低 32 位
- 高32位为 选举leader 的纪元编号
- 低32位位事务编号
Watcher- zookeeper 提供了 两种 类型的 watcher
- 节点数据变化的 watcher
- 节点变化的 watcher
A. 节点数据变化的监听[AppleScript] 纯文本查看 复制代码 zk: get 路径 watch
B. 节点变化的监听- 监听只能监听一次,每次收到监听后再注册一次监听
- 不能监听节点的节点发生变化
[AppleScript] 纯文本查看 复制代码 zk: ls 路径 watch
leader 选举机制- zookeeper 集群安装数量最好是奇数台,因为 zookeeper 集群中没有固定的 leader,leader 是动态选举出来的
- 选举规则: 哪个节点的票数多,哪个节点就是 leader
- leader 的选举过程(假设 3 台节点, 每台节点都配置了 id)
- 每个 zookeeper 节点都有一个 myid 文件,里面的编号都不能重复
- 新集群
- 第一个节点启动(myid = 1),查看集群中是否有 leader,结果发现没有 leader
- 给自己投一票,我要当 leader
- 并把这个消息广播给其他节点
- 第二个节点启动(myid = 2),查看集群中是否有 leader,结果发现也没有 leader
- 同时会收到第一个节点的广播消息(第一个节点投自己一票)
- 节点2发现自己的 id 比节点1 的大,n2 自己投一票,并广播消息
- 节点1收到节点2的投票,发现自己的id比节点2小,投节点2一票
- 此时节点2的票数超过一半
- 节点2切换到 leader 状态
- 节点1切换到 follow 状态
- 节点3启动发现集群中有 leader 了,切换到 follow 状态
- 运行过程中 leader 宕机了,则重新进行 leader 选举
- 投票规则:谁的数据版本最新则选举谁为 leader, 如果数据版本一致,则谁的 id 大选举谁为 leader
zookeeper 集群搭建概述- http://zookeeper.apache.org/releases.html 下载最新版本的 zookeeper
- 解压
[AppleScript] 纯文本查看 复制代码 tar -zxf zookeeper-3.4.6.tar.gz -C /soft/
修改配置 - 进入 zookeeper 的 conf 目录下, 重命名 zoo_sample.cfg 为 zoo.cfg
[AppleScript] 纯文本查看 复制代码 $ mv zoo_sample.cfg zoo.cfg
$ vi zoo.cfg
tickTime = 2000
dataDir = /soft/zookeeper-3.4.6/zkdata
clientPort = 2181
initLimit = 5
syncLimit = 2
server.1=ido01:2888:3888
server.2=ido02:2888:3888
server.3=ido03:2888:3888
[AppleScript] 纯文本查看 复制代码 "ido01"
$ echo 1 > /sfot/zookeeper-3.4.6/zkdata/myid
"ido02"
$ echo 2 > /sfot/zookeeper-3.4.6/zkdata/myid
"ido03"
$ echo 3 > /soft/zookeeper-3.4.6/zkdata/myid
[AppleScript] 纯文本查看 复制代码 bin/zkServer.sh restart
[AppleScript] 纯文本查看 复制代码 停止 zookeeper
[AppleScript] 纯文本查看 复制代码 bin/zkServer.sh stop
|