命令:
stat path [watch]
set path data [version]
ls path [watch]
delquota [-n|-b] path
ls2 path [watch]
setAcl path acl
setquota -n|-b val path
history
redo cmdno
printwatches on|off
delete path [version]
sync path
listquota path
rmr path
get path [watch]
create [-s] [-e] path data acl
addauth scheme auth
quit
参考:
Zookeeper 环境搭建&zk命令详解
优点:高效读写
为什么ZK不擅长存储大的数据?
需要多次访问磁盘块,IO耗时严重
乐观锁
version 数据节点内容版本号
cversion 数据节点子节点版本号
aversion ACL变更版本号
高效写磁盘的两种方式:
ZK每次写磁盘,先申请固定大小的磁盘空间,之后再写磁盘,大大提升写入性能。写的时候预先申请固定大小的磁盘空间(64M),这样能高效顺序写磁盘,再把数据序列化后写入磁盘。可以先写数据到磁盘缓冲区oscache中,再定期刷到磁盘中。
乐观锁保证原子操作,并发写只有一个能成功,且能支持顺序生成一个数据,如ID。写的时候,先写事务日志,在写ZKDatabase,保证数据不丢失。
每次写入操作,ZooKeeper会附加一个数字标签,表明ZooKeeper中的事务顺序
快照+事务日志
什么时候记录事务日志?事务操作时,先记录事务日志,再操作内存ZKDatabase。
如何快照?新起线程,不影响主流程
内存数据 ZKDatabase DataTree DataNode nodes
事务日志 写入时申请磁盘64M 写入文件流后 配置是否刷盘
数据快照 可配置多少次事务日志记录后进行一次快照,启动单独异步线程dump数据,不影响主线程的任务。
宕机后重启,初始化 -> 尝试加载最近的100个快照,逐一加载,无法成功则报错 -> 加载未加载到的事务日志
一主多从结构,只有一台master服务器对外提供写服务,每次写记录ZXID事务Id。原子写,保证mei yo
写的策略,半数以上机器写成功后返回。
写数据流程,非Leader节点会把请求转发给leader,写成功后leader再通知该节点。
ZAB(Zookeeper Atomic Broadcast)协议:初始阶段/宕机恢复(原子广播)
ZAB(Zookeeper Atomic Broadcast)协议?
ZAB协议的核心定义了对于那些改变ZooKeeper服务器数据状态的事务请求的处理方式。即,所有事务请求必须有一个全局唯一的服务器来协调处理,这样的服务器被称为Leader服务器,而余下的其他服务器则成为Follower服务器。Leader服务器负责将一个客户端事务请求转换成一个事务Proposal(提议),并将该Proposal分发给集群中所有的Follower服务器。之后Leader服务器需要等待所有Follower服务器的反馈,一旦超过半数的Follower服务器进行了正确的反馈后,那么Leader就会再次向所有的Follower服务器分发Commit消息,要求其将前一个Proposal进行提交。(ZooKeeper中还有一种机器角色:Observer。Observer机器不参与Leader选举过程,也不参与写操作的“过半写成功”策略,因此Observer可以在不影响写性能的情况下提升集群的读性能)
Zookeeper 的核心是原子广播,这个机制保证了各个Server之间的同步。实现这个机制的协议叫做Zab协议。Zab协议有两种模式,它们分别是恢复模式(选主-Leader选举)和广播模式(数据同步)。
Leader选举–初始阶段/宕机恢复(原子广播)如何进行?
数据同步
Leader服务器会为每一个Follower服务器准备一个队列,并将那些没有被各个Follower服务器同步的事务以Proposal的形式逐条发给各个Follower服务器,并在每一个Proposal后都紧跟一个commit消息,表示该事务已经被提交,档follower服务器将所有尚未同步的事务proposal都从leader服务器同步过来并成功应用到本地后,leader服务器就会将该follower加入到真正可用的follower列表中。
follower节点,observer节点都可以对外提供读数据能力
客户端读的时候,需要最新的数据?
客户端在调用前,可以先申请连接的主机同步leader数据,调用sync()方法 ,之后再读取数据。
ZK做的不好的地方。
ZooKeeper 在水平扩容扩容方面做得并不十分完美,需要进行整个集群的重启。通常有两种重启方式,一种是集群整体重启,另外一种是逐台进行服务器的重启。
整体重启
所谓集群整体重启,就是先将整个集群停止,然后更新 ZooKeeper 的配置,然后再次启动。如果在你的系统中,ZooKeeper 并不是个非常核心的组件,并且能够允许短暂的服务停止(通常是几秒钟的时间间隔),那么不妨选择这种方式。在整体重启的过程中,所有该集群的客户端都无法连接上集群。等到集群再次启动,这些客户端就能够自动连接上——注意,整体启动前建立起的客户端会话,并不会因为此次整体重启而失效。也就是说,在整体重启期间花费的时间将不计入会话超时时间的计算中。
逐台重启
这种方式更适合绝大多数的实际场景。在这种方式中,每次仅仅重启集群中的一台机器,然后逐台对整个集群中的机器进行重启操作。这种方式可以在重启期间依然保证集群对外的正常服务。
Watcher(实现较简单,可以改进)
ACL
扩展:
Zookeeper的两大特性(节点特性和watcher机制):
支持的特性包括:
Hadoop
Hbase
Kafka
Dubbo
JStorm
基本原理是,每个应用的Server启动时创建一个EPHEMERAL(临时)节点,应用客户端通过读取节点列表获得可用服务器列表,并订阅节点事件,有Server宕机断开时触发事件,客户端监测到后把该Server从可用列表中删除
基本原理:通过调用Zookeeper节点创建的API接口就可以创建一个顺序节点,并且在API返回值中会返回这个节点的完整名字,利用此特性,可以生成全局ID,其步骤如下
基本原理,利用Zookeeper的一致性,能够很好地保证在分布式高并发情况下节点的创建一定能够保证全局唯一性,即Zookeeper将会保证客户端无法重复创建一个已经存在的数据节点(由其分布式数据的一致性保证)。
首先创建/master_election/2016-11-12节点,客户端集群每天会定时往该节点下创建临时节点,如/master_election/2016-11-12/binding,这个过程中,只有一个客户端能够成功创建,此时其变成master,其他节点都会在节点/master_election/2016-11-12上注册一个子节点变更的Watcher,用于监控当前的Master机器是否存活,一旦发现当前Master挂了,其余客户端将会重新进行Master选举
实现方案:
① FIFO先入先出,先进入队列的请求操作先完成后,才会开始处理后面的请求。FIFO队列就类似于全写的共享模型,所有客户端都会到/queue_fifo这个节点下创建一个临时节点,如/queue_fifo/host1-00000001。
创建完节点后,按照如下步骤执行。
② Barrier分布式屏障,最终的合并计算需要基于很多并行计算的子结果来进行,开始时,/queue_barrier节点已经默认存在,并且将结点数据内容赋值为数字n来代表Barrier值,之后,所有客户端都会到/queue_barrier节点下创建一个临时节点,例如/queue_barrier/host1。
创建完节点后,按照如下步骤执行。
Zookeeper 和 Etcd 都是非常优秀的分布式协调系统,zookeeper 起源于 Hadoop 生态系统,etcd 的流行是因为它是 kubernetes 的后台支撑。
优点
缺点
特性:
优点:
缺点
参考:
Java Web分布式篇之ZooKeeper
初识ZooKeeper
Zookeeper vs Etcd
zookeeper与etcd的对比