zookeeper
基础
概要
-
ZooKeeper 是一个开源的分布式协调服务。它是一个为分布式应用提供一致性服务的软件,分布式应用程序可以基于 Zookeeper 实现诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master 选举、分布式锁和分布式队列等功能。
- ZooKeeper的数据存储在一个叫 ReplicatedDataBase 的 数据库中,该数据是一个内存数据库(concurrentHashMap);zookeeper通过:Znode结构特性+节点关联的数据实现上述功能
-
zookeeper集群的特性:zookeeper集群之所以能保持上面的功能主要是因为其具有(使用zab协议):
-
顺序性:所有事务请求会顺序执行:偏序和全局有序
- 全局有序:server发布a、b事务,先发布者在全局均会先于后发布者处理
- 偏序:服务端内部有序
-
原子性:zookeeper的事务具有原子性;
-
单一视图:无论客户端连接在任意zookeeper服务器,任何时候其所能看到的数据模型都是一致的;
-
可靠性:事务提交成功后具有持久性;
-
最终一致性
-
-
ZooKeeper 的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户。
四字命令:附录(重点)
使用:https://www.cnblogs.com/crazylqy/p/7131881.html
会话
-
session**:zookeeper通过TCP连接客户端和zookeeper服务程序;通过一个sessionID区分不同的客户端**
-
sessionID为时间戳+客户端连接的serverID:时间戳之所以右移8位为serverid腾出空间,所以集群中server的数量最多2^8-1==255个
-
sessionId = ((timestamp << 24) >> 8) | (sid << 56)
-
-
session状态:
- connecting:建立连接中
- connected:连接已建立,且处于存活期中
- zookeeper 的 leader 服务器运行期间定时进行会话超时检查,通过分桶策略管理大量的会话;
- 检查的时间间隔是 ExpirationInterval,单位是毫秒,默认值是 tickTime,tickTime下次会话超时时间点,默认 2000 毫秒
- 每隔 tickTime 进行一次会话超时检查。
- closing:连接关闭;由于网络故障客户端重连失败,服务器宕机或者客户端主动断开。
-
分桶策略
-
- 分桶策略:zookeeper通过将过期时间相同的放入一个桶中:上下图表示分桶策略的处理过程;首先每次收到(get/put、PING )请求的时候更新当前会话到下一个过期桶中,每隔一段时间将到期桶的所有会话关闭;
-
-
持久化
https://www.jianshu.com/p/95931a34f565
单机
(模拟)文件系统
节点Znode
基础
![image-20220311094705578](https://i-blog.csdnimg.cn/blog_migrate/c73cff6bbdc07495ebd35fdc8899bbdf.png)
- 文件节点类型:znode分为临时节点和持久节点、普通节点和顺序节点:
- 临时节点:临时节点不能有子节点,在session关闭后自动(且过了ttl后)销毁;
- 持久节点:创建后如果不手动销毁将永久在zookeeper目录中;
- 顺序节点和普通节点:临时/持久节点可以分为顺序和普通类型;顺序节点会在定义的文件名的后面自动加上一个10位数的自动增加的序列号,这个计数对于此节点的父节点是唯一,如果这个序列号大于2^32-1就会溢出。;普通节点则使用自定义的文件名作为文件名
- 节点的属性:见下文附录,重点介绍三个:(正是由于文件具有节点的各种版本号,所以每次对于文件的修改可以对照版本号,通过版本号实现乐观锁功能;)
- cversion:子节点号,每次对于子节点的增删改就自动加1
- dataversion 数据版本号,数据每次修改该版本号加1
- aclversion 权限版本号,权限每次修改该版本号加1
- xxxZxid:xxx事务id
- 节点的特性
- 节点key(名称)具有:目录唯一性;
- 节点的创建需要指定完整目录;
- 节点的删除必须逐层删除,没有子节点才可以删除本节点【deleteall递归删除子节点再删除本节点】
- 自动创建顺序节点和临时节点
- watch机制监控指定的节点的变化
- 节点权限:增c、删d、改w、查r、管理a五种权限
- setAcl、getAcl、addauth:设置获取和添加某一节点的权限
- 总的来说
-
节点特性
-
乐观锁机制(数据版本、权限版本、子节点版本)
-
持久化机制
- 临时节点(在会话关闭自动销毁)
- 持久节点
-
节点名机制
- 顺序节点或者普通节点
-
watch机制(监视乐观锁变化)
-
-
文件特性
- 权限
- 目录唯一
- 目录下文件名不可重复
-
总结
- 分布式锁:zookeeper通过:临时节点特性和文件目录名的唯一性实现分布式锁和监听机制;例如在目录/appName/lock/myLock下进行操作:在该目录的子目录下建立临时的顺序节点
- 读锁:(可重入设置一个data:read_count计算重入的次数)
- 公平锁:(先检查本session是否在该位置已经获取到锁,否则)若当前存在的所有顺序节点均为读请求,则获得锁;否则监听比当前节点小的最大的写锁节点的状态;
- 写锁:(可重入设置一个data:write_count计算重入的次数)
- 公平锁:(先检查本session是否在该位置已经获取到锁,否则)如果自己不是序号最小的子节点,那么就进入等待,并监听比当前节点小的最大序列号请求节点。
- 公平和非公平:
- 读锁:(可重入设置一个data:read_count计算重入的次数)
- 数据发布/订阅:通过watch实现;很明显只需要保证让需要订阅的session同时watch某一个节点即可;例如/appName/publish/xxxx
- 命名服务:利用临时节点+watch:
-
- 利用zookeeper的心跳机制实时监控注册服务状态,删除无效服务节点,维护有效的地址注册表。
- 轮询服务注册表,尽可能将服务请求均匀分配到所有注册有效的服务器上。
- 通过统计注册表各个子节点被访问次数来监控服务调用情况。
-
数据模型
数据库
ZKDatabase
protected DataTree dataTree;
protected FileTxnSnapLog snapLog;
protected long minCommittedLog, maxCommittedLog;
protected LinkedList<Proposal> committedLog = new LinkedList<Proposal>();
DataTree
private final ConcurrentHashMap<String, DataNode> nodes =
new ConcurrentHashMap<String, DataNode>();
DataNode
- ZKDatabase
- Zookeeper的内存数据库,管理Zookeeper的所有会话、DataTree存储和事务日志。ZKDatabase会定时向磁盘dump快照数据,同时在Zookeeper启动时,会通过磁盘的事务日志和快照文件恢复成一个完整的内存数据库。
- DataTree:DataTree通过ConcurrentHashMap模拟文件系统,key为文件路径,value为节点的信息;
- DataNode:即Znode,是zookeeper数据库的最小存储单元
日志系统
https://www.cnblogs.com/leesf456/p/6179118.html
通知机制
- watch机制:客户端注册监听它关心的目录节点,当目录节点发生变化(数据改变、被删除、子目录节点增加删除)时,zookeeper会通知客户端。
- 特点:
- "监视点"是一次性的,当触发过一次之后,除非重新设置,新的数据变化不会提醒客户端。
- "监视点"将数据改变的通知客户端。如果数据改变是客户端A引起的,不能保证"监视点"通知事件会在引发数据修改的函数返回前到达客户端A。
- 对于"监视点",ZooKeeper有如下保证:客户端一定是在接收到"监视"事件(watch event)之后才接收到数据的改变信息。
- 断线重连后会自动再注册监视点,但是如果:客户端B设置了关于节点A存在性的"监视点",但B断线了,在B断线过程中节点A被创建又被删除。此时,B再连线后不知道A节点曾经被创建过。
- **一个监控对象,只会被相关的通知触发一次。**如果一个客户端设置了关于某个数据点exists和getData的监控,则当该数据被删除的时候,只会触发"文件被删除"的
- ZooKeeper客户端可以自动地进行故障切换,切换至另一台ZooKeeper服务器。并且关键的一点是,在另一台服务器接替故障服务器之后,所有的会话和相关的短暂Znode仍然是有效的。在故障切换过程中,应用程序将收到断开连接和连接至服务的通知。当客户端断开连接时,观察通知将无法发送;
集群
- zookeeper集群是一个CP系统,为什么是CP系统呢?
zab
- zab(Zookeeper 原子广播协议):是zookeeper的分布式算法,其节点角色为:leader、Follower;
- zab使用一主多从的模式
- zab算法核心作用是
- leader宕机后,其已经commit的事务不丢失;没有commit的事务均抛弃;
- 保证事务的顺序性、原子
- 保证单一视图和最终一致性
- 集群的三个阶段
- 发现
- 在这个阶段,Followers 和上一轮选举出的准 Leader 进行通信,同步 Followers 最近接收的事务 Proposal 。
- 同步
- 同步阶段主要是利用 Leader 前一阶段获得的最新 Proposal 历史,同步集群中所有的副本。
- 只有当 quorum(超过半数的节点) 都同步完成,准 Leader 才会成为真正的 Leader。Follower 只会接收 zxid 比自己 lastZxid 大的 Proposal。
- 广播
- 和2PC类似
- leader先提交预案、follower日志先行(日志完成返回YES),leader收到半数YES,发起commit,从节点收到commit则完成事务提交;
- 主节点和各个从节点均有一个FIFO的事务队列(避免丢失和阻塞主节点)
- leader先提交预案、follower日志先行(日志完成返回YES),leader收到半数YES,发起commit,从节点收到commit则完成事务提交;
- 和2PC类似
- 发现
- 两种模式
- 崩溃恢复
- 一旦 Leader 服务器出现崩溃或者由于网络原因导致 Leader 服务器失去了与过半 Follower 的联系,那么就会进入崩溃恢复模式。
- 新选举出来的 Leader 不能包含未提交的 Proposal。
- 新选举的 Leader 节点中含有最大的 zxid。
- 信息广播
- 崩溃恢复
附录
节点
-
节点属性
-
cZxid 创建节点时的事务ID ctime 创建节点时的时间 mZxid 最后修改节点时的事务ID mtime 最后修改节点时的时间 pZxid 表示该节点的子节点列表最后一次修改的事务ID,添加子节点或删除子节点就会影响子节点列表,但是修改子节点的数据内容则不影响该ID cversion 子节点版本号,子节点每次修改版本号加1 dataversion 数据版本号,数据每次修改该版本号加1 aclversion 权限版本号,权限每次修改该版本号加1 dataLength 该节点的数据长度 numChildren 该节点拥有子节点的数量
-
命令
https://blog.csdn.net/dandandeshangni/article/details/80558383
前面已经介绍过zookeeper是一个简易的文件系统,所以简单来说zookeeper命令分为:文件操作命令和权限命令:
1.文件操作命令
ls /节点 #查看当前节点所以文件
get /节点 #获取节点内容
stat /节点 #获取节点信息(前面节点信息
ls2 /节点#ls+stat命令组合
create #创建节点
delete /节点/版本号 #删除节点
watcher #创建监听通知 (当每个节点发生变化,都会触发watcher事件,类似于mysql的触发器。zk中 watcher是一次性的,触发后立即销毁。)
2.权限命令(ZK的节点有5种操作权限:CREATE、READ、WRITE、DELETE、ADMIN 也就是 增、删、改、查、管理权限)
# 使用[scheme:id:permissions]来表示acl权限,
-- world:默认方式,相当于全世界都能访问:
-- auth:代表已经认证通过的用户(cli中可以通过addauth
-- digest user:pwd 来添加当前上下文中的授权用户);
-- digest:即用户名:密码这种方式认证,这也是业务系统中最常用的;ip:使用Ip地址认证
3.四字命令