共计 3167 个字符,预计需要花费 8 分钟才能阅读完成。
Zookeeper 概念
-
Zookeeper 是分布式协调服务, 用于治理大型主机, 在分布式环境中协调和治理服务是很简单的过程,Zookeeper 通过简略的架构和 API 解决了这个问题
Zookeeper 实现分布式锁
分布式锁三要素: 加锁 解锁 锁超时
- Zookeeper 数据结构相似树结构, 由节点 Znode 组成
-
Znode 分为四种类型:
- 长久节点(PERSISTENT): 默认节点类型, 创立节点的客户端与 Zookeeper 断开连接后, 节点仍旧存在
- 长久节点程序节点(PERSISTENT_SEQUENTIAL): 长久节点程序节点就是在创立长久节点时,Zookeeper 依据创立节点的工夫程序给节点进行编号
- 长期节点(EPHEMERAL): 创立节点的客户端与 Zookeeper 断开连接后, 长期节点会被删除
- 长期节点程序节点(EPHEMERAL_SEQUENTIAL): 长期节点程序节点就是在创立长期节点时,Zookeeper 依据创立节点的工夫程序给节点进行编号
- 利用 Zookeeper 的长期程序节点, 实现分布式锁
Zookeeper 与 Redis 分布式锁比拟:
分布式锁 | Zookeeper | Redis |
---|---|---|
长处 | 1. 有封装好的框架, 容易实现 2. 有期待锁队列, 晋升抢锁的效率 |
Set 和 Del 指令性能高 |
毛病 | 增加和删除节点性能低 | 1. 实现简单, 须要思考原子性, 误删, 锁超时问题 2. 没有期待锁的队列, 只能客户端自旋来等锁, 效率低 |
Zookeeper 的数据模型
- 相似数据结构中的树, 文件系统中的目录
- Zookeeper 的数据存储基于节点 Znode
-
Znode 的援用形式是门路援用, 每一个 Znode 节点领有惟一的门路
Znode 中的元素
- data: Znode 存储的数据信息
- ACL: 记录 Znode 的拜访权限, 即哪些过程和 IP 能够拜访本节点
- stat: Znode 的各种元数据(数据的数据)
-
child: 以后节点的子节点援用
Zookeeper 的利用场景是读多写少的利用场景:Znode 不用来存储大规模的业务数据, 用于存储大量的状态和配置信息(Znode 存储数据不能超过 1MB)Zookeeper 基本操作
- 创立节点:create
- 删除节点:delete
- 判断节点是否存在:exists
- 取得一个节点的数据:getData
- 设置一个节点的数据:setData
-
获取节点下的所有子节点:getChildren
exists,getData,getChildren 属于读操作,Zookeeper 客户端在申请读操作时, 能够抉择是否设置 watchZookeeper 事件告诉
- Watch能够了解成注册在特定 Znode 上的触发器
- 当 Znode 产生扭转的时候, 调用 create,delete,setData 办法, 将会触发 Znode 上注册的对应事件, 申请的 Watch 的客户端会接管到异步告诉
-
Zookeeper 事件告诉的交互过程:
- 客户端调用 getData 办法,watch 的参数是 true, 服务端接管到申请, 返回节点数据, 在对应的 Hash 表中插入被 Watch 的 Znode 门路以及 Watcher 列表
-
当被 Watch 的 Znode 删除, 服务端会查找 Hash 表, 找到该 Znode 对应的所有 Watcher, 异步告诉客户端, 并且删除 Hash 表中对应的 key-value
Zookeeper 的一致性
- Zookeeper Service 集群是 一主多从 构造
- 在更新数据时, 首先更新到主服务器, 再同步到从服务器
- 在读数据时, 间接读取任意节点
-
采纳 ZAB 协定, 为了保障主从节点数据的一致性
ZAB 协定
- ZAB(Zookeeper Automic Broadcast): 解决 Zookeeper 集群解体复原, 主从数据同步问题
-
ZAB 三种节点状态:
- Looking: 选举状态
- Following:Following 节点 (从节点) 所处的状态
- Leading:Leading(主节点)所处的状态
-
最大 ZXID: 节点本地的最新事务编号, 蕴含 epoch 和计数 两局部
ZAB 集群解体复原
-
当 Zookeeper 的主节点服务器宕机后, 集群就会进行解体复原, 分成三个阶段:
-
Leader election(选举阶段):
- 集群中的节点处于 Looking 状态, 各自向其它节点发动投票, 投票当中蕴含本人服务器的 ID 和最新事务 ID(ZXID)
- 节点用本身的 ZXID 和其它节点收到的 ZXID 作比拟, 如果发现其它节点的 ZXID 比本身大, 即数据比本人新, 就从新发动投票, 投票给目前已知最大 ZXID 所属节点
- 每次投票后, 服务器都会统计投票数量, 判断是否某个节点失去半数以上的投票, 这样的节点将会成为准 Leader, 状态变为 Leading, 其它节点状态变为 Following
-
Discovery(发现阶段):
- 在从节点发现最新的 ZXID 和事务日志, 目标是为了避免在意外状况, 选举产生多个 Leader
- Leader 接管所有 Follower 发送的最新的 epoch 值,Leader 从中选出最大的 epoch, 基于此值 +1, 生成新的 epoch 分发给各个 Follower
- 各个 Follower 接管到最新的 epoch, 返回 ACK(响应码)给 Leader, 带上各自最大的 ZXID 和历史事务日志,Leader 选出最大的 ZXID, 并更新本身历史日志
-
Synchronization(同步阶段):
-
将 Leader 收集失去的最新历史事务日志, 同步给集群中的所有 Follower, 只有当半数 Follower 同步胜利, 这个准 Leader 能力成为正式 Leader. 集群解体复原正式实现
ZAB 主从数据同步
-
-
-
Broadcast
Zookeeper 惯例状况下更新数据的时候, 由 Leader 播送到所有的 Follower:- 客户端收回写入数据申请给任意的 Follower
- Follower 把写入数据申请转发给 Leader
- Leader 采取 二阶段提交形式:(先保留提交日志, 再提交数据)先发送 Propose 播送给 Follower
- Follower 接管到 Propose 音讯, 写入日志胜利后, 返回 ACK 音讯给 Leader
-
Leader 接管到半数以上的 ACK 音讯, 返回胜利给客户端, 并且播送 commit 申请给 Follower
数据一致性: 强一致性 弱一致性 程序一致性:Zookeeper, 依附事务 ID 和版本号, 保证数据的更新和读取是有序的
Zookeeper 利用场景
- 分布式锁: 利用 Zookeeper 的长期程序节点, 实现分布式锁
- 服务注册与发现: 利用 Znode 和 Watcher, 实现分布式服务注册与发现, 如 Dubbo
- 共享配置和状态信息: Redis 的分布式解决方案 Codls, 利用 Zookeeper 存放数据路由表和 codls-proxy 节点元信息, 同时 colds-config 发动的命令都会通过 Zookeeper 同步到各个存活的 codls-proxy
-
高可用实现: Kafka,HBase,Hadoop 都依附 Zookeeper 同步节点信息, 实现高可用
基于 Docker 创立 Zookeeper
1. 创立 docker-compose.yml zoo: image: zookeeper restart: always hostname: zoo ports: - 2181:2181 environment: - ZOO_MY_ID: 1 - ZOO_SERVER: server.1(id)=zoo(IP):2888:3888 2. 执行 docker-compose up -d
Zookeeper 三种工作模式
- 单机模式: 存在单点故障
- 集群模式: 在多台服务器上部署 Zookeeper 集群
-
伪集群模式: 在同一台服务器上运行多个 Zookeeper 实例, 依然有单点故障问题, 其中配置的端口号要错开
Zookeeper 三种端口号
- 2181: 客户端连贯 Zookeeper 集群应用的监听端口号
- 3888: 选举 Leader 应用
- 2888: 集群内机器通信应用(Leader 和 Follower 之间数据同步应用的端口号,Leader 监听此端口)