序言:
文章内容输出来源:拉勾教育Java高薪训练营。
本篇文章是学习课程中的一部分课后笔记
一、简介
1、zookeeper 概述
一个开源分布式协调服务,分布式数据一致性解决方案(共享存储)
可实现 数据订阅/发布、负载均衡、命名服务、集群管理、分布式锁、分布式队列等功能
2、基本概念
-
集群角色
- leader :为客户端提供读和写服务
- follower : 提供读的服务,参与leader选举,写操作的过半写成功策略
- observer : 提供读的服务
会话(session)
客户端和服务端之间的一个tcp长连接,通过这个连接,客户端能够心跳检测与服务端保持有效会话,也能够向服务端发送请求并接受响应,还能接收服务端的watch事件通知。-
数据节点(znode)
- 机器节点 : 集群的机器
- 数据节点 : 数据模型中的数据单元 , /app/path (内存树 znode tree 中的节点信息)
-
版本
一个stat 的数据结构,记录znode的三个数据版本:- version (znode的版本)
- cversion (znode子节点的版本)
- aversion (znode 的ACL 版本)
-
watcher (事件监听器)
- 允许用户在指定节点注册watcher,在一些特定事件触发的时候,zookeeper 服务端会将事件通知到感兴趣的客户端。
-
流程:客户端向zookeeper服务器注册的同时,会将watcher对象存储在客户端watcherManager中,当zookeeper触发watcher事件后,会向客户端发送通知,客户端从watcherManager中取出对应的watcher 对象来执行回调逻辑。
watcher.png
-
ACL
采用 ACL( Access Control Lists ) 策略进行权限控制:- create :创建子节点权限
- read :获取节点数据&子节点列表权限
- write : 更新节点数据权限
- delete : 删除子节点的权限
- admin :设置节点ACL的权限
create & delete 都是针对子节点的权限控制
通常使用"scheme:id:permission" 标识一个有效的acl信息。
权限模式(scheme)、授权对象(id)、权限(permission)

二、系统模型
1、zookeeper 数据模型

2、ZNode 的类型
-
持久性节点
- 节点被创建后会一直存在服务器中,直到删除操作主动清楚
-
临时性节点
- 生命周期和客户端会话绑在一起,客户端会话结束,节点会被删除掉,不能创建子节点。
-
顺序性节点
- 附加到持久性节点与临时性节点的属性
三、应用场景
1、数据发布/订阅
- 一般有两种设计模式:推(push) 和 拉(pull)
例:
-
配置存储
将一些初始化配置信息存储到zookeeper上,如:
配置信息.png - 配置获取
集群中每台机器在启动初始化阶段,首先都会从配置节点中读取信息,同时,客户端还需要在该配置节点注册一个watcher监听,一旦发生节点数据变更,所有订阅的客户端都能得到通知。 - 配置更新
只需要对zookeeper上配置的节点内容进行更新,就能将变化的数据通知到各个客户端,客户端同步获取最新数据。
2、命名服务(全局唯一id分配机制)

生成唯一ID的基本步骤:
1、所有客户端都会根据自己的任务类型,在指定的类型的任务下面通过调用create创建
一个顺序节点。
2 、create()会返回一个完整的节点名。如"job-0000000003"
3、客户端拿到完整的节点名后,拼接上type类型,"type2-job-0000000003",就可以是全局唯一的id了。
3、集群管理
zk的两大特性:
- 客户端如果对数据节点注册watcher监听,那么当该数据节点的内容或是其子节点列表发生变更时,zk服务器就会向订阅的客户端发送变更通知。
- 对在zk上创建的临时节点,一旦客户端与服务器之间的会话失效,那么临时节点也会被自动删除。
利用其两大特性,就可以实现集群机器存活监控系统。
若监控系统在/clusterServers节点上注册一个watcher监听,那么但凡进行动态的添加机器操作,就会在/clusterServers节点上创建一个临时节点,这样就能实时检测机器的变动情况。
4、分布式锁
- 排他锁
- 如果事务T1对数据对象O1添加了排他锁,那么在整个加锁期间,只允许事务T1对O1进行读取和更新操作,其他事务都不能对O1进行任何类型操作----直到T1释放了排他锁。
ZK实现排他锁:
① 定义锁
java中通过synchronized机制与jdk1.5提供的ReentrantLock。
zk通过定义数据节点,定义为一个锁:

② 获取锁
客户端通过create()来创建临时节点,zk保证了最终只能一个客户端创建成功,其他没成功在该节点注册一个watcher监听,实时监听lock节点的变更情况。
③ 释放锁
情况一:当获取锁的客户端宕机,zk的临时节点就会被移除。
情况二:正常执行完业务逻辑后,客户端会主动删除自己创建的临时节点。

-
共享锁
- 如果事务T1对数据对象O1加上了共享锁,那么当前事务只能对O1进行读取操作,其他事务也只能对该数据对象加共享锁——直到该对象上的所有共享锁都被释放。
排他锁&共享锁根本区别:
- 加了排他锁,数据对象只对一个事务可见。
- 加了共享锁,数据对象对所有事务可见。
① 定义锁
创建临时有序节点:
定义锁.png② 获取锁
创建临时有序节点,如果是读请求添加R类似的标识,写请求添加W类似标识。
ZK判断读写顺序:

③ 释放锁
与排他锁释放机制一样。
- 羊群效应

当ZK的所有子节点都注册watcher到host1时,当host1移除自己的共享锁之后,除了host2产生影响外(序号最小,进行写操作),其他机器都继续等待。
大量watcher通知和子节点列表获取两个操作会重复运行,影响性能与网络开销。
优化的逻辑核心:关注比自己序号小的那个相关节点的变更情况即可。

5、分布队列
-
FIFO先入先出
类似一个全是写操作的共享锁:
FIFO.png
- Barrier:分布式屏障
对一个节点数据内容赋值一个数字n代表barrier值,当字节点个数达到n后,才会打开barrier。
场景: 分布式并行计算,最终的合并计算需要基于很多并行计算的子结果来进行。
barrier.png
四、ZAB协议
1、ZAB概述
zookeeper Atomic Broadcast (原子消息广播协议),支持崩溃恢复的原子广播协议的分布式一致性算法。
2、ZAB核心
-
定义了对于那些会改变zk服务器数据状态的事务请求的处理方式。
ZAB核心.png
3、崩溃恢复
leader服务器出现异常情况,ZAB进入崩溃恢复模式,同时选举产生新的leader服务器。
当集群中已经有过半的机器与该leader服务器完成状态同步(数据同步)之后,ZAB协议就会退出崩溃恢复模式。
4、消息广播(类似二阶提交过程)
当集群中已经有过半的follower服务器完成了和leader服务器的状态同步,整个服务框架就可以进入消息广播模式。
当新加入一台机器,就会进入数据恢复模式,找到leader所在服务器,并与其进行数据同步,然后一起参与到消息广播流程中去。







