Zookeeper是一个分布式协调框架,近年来已经成为一个热门的话题,不懂用法及原理几乎会被鄙视。下面将分享下,很久之前的笔记,同时也喜欢可以达到为故而知新的目的。
目录
1.介绍
2.应用场景
3.基本概念
3.1.Paxos算法
3.2. ZAB协议
3.3. 选举
3.4. 集群角色
3.5. 会话
3.6. 数据模型
3.7. 数据节点
3.8. 版本
3.9. Wacher
3.10. ACL
4.架构
4.1.工作原理
4.2.读写机制
5.安装
6.命令行
7.Java客户端
7.1.默认端口
7.2.Java原生
7.3.Apache Curator
7.4.zkclient
8.HDFS的分布式锁
9.目前不足
ZooKeeper是一个开源、高性能、数据一致性、分布式协调服务,它是开源的Hadoop项目中的一个子项目,是Hadoop和Hbase的重要组件。并且根据google发表的
ZooKeeper是google的Chubby一个开源的实现,它包含一个简单的原语集,分布式应用程序可以基于它实现同步服务、配置维护和命名服务等。
1.数据发布/订阅
也就是配置中心的概念,分为发布者和订阅者
2.负载均衡
通过ZK管理集群中服务提供方的域名及ip及端口,dubbo服务框架就是基于ZK实现服务路由和负载
3.命名服务
名称的服务,通过ZK可以实现类似于J2EE中JNDI的效果,在分布式环境下,更多是资源的定位,并不是真正实体资源;
例如数据库表ID,一种是自增ID,一种是UUID而ZK就可以很好的解决;
4.分布式协调/通知
它是一个基于消息传递的一致性算法,在1990年被提出,比如google的chubby,aapache的zookeeper都是基于它的理论。
包含的角色有:
Proposer(申请者)、Acceptor(接收者)、Learner(领导者);
执行过程:
优点:引入“过半”的概念,即少数服从多数的原则,并且支持节点角色之间的轮换,极大地避免了分布式的出现,也解决了无限等待和“脑裂”等问题。
为分布式协调服务Zookeeper专门设计的一种支持崩溃恢复的原子广播协议。它规定任何时候都需要保证只有一个主进程负责进行消息广播,如果主进程崩溃了就要选举一个新的主进程,选举机制和消息广播机制是紧密相关。ZAB协议包括两种基本模式:崩溃恢复和消息广播。
为了保证事务的顺序一致性,ZooKeeper采用了递增事务id号(zxid)来标识事务。所有的提议(proposal)都在被提出的时候加上了zxid,实现中zxid是一个64位的数字,它前32位是用epoch来标识leader关系是否改变,每次leader被选出来,它都是一个新的epoch,标识当前属于哪个leader的统治时期。后32位用于递增计数。
每个server在工作过程中有三种状态:
ZAB与Paxos的联系与区别:
半数通过,奇数台部署可以满足挂一台继续有效选举。
- 变更状态。Leader挂后,余下的非Observer服务器都会讲自己的服务器状态变更为LOOKING,然后开始进入Leader选举过程。
- 每个Server会发出一个投票。在运行期间,每个服务器上的ZXID可能不同,此时假定Server1的ZXID为123,Server3的ZXID为122;在第一轮投票中,Server1和Server3都会投自己,产生投票(1, 123),(3, 122),然后各自将投票发送给集群中所有机器。
- 接收来自各个服务器的投票。与启动时过程相同。
- 处理投票。与启动时过程相同,此时,Server1将会成为Leader。
- 统计投票。与启动时过程相同。
- 改变服务器的状态。与启动时过程相同。
要确保Zookeeper能够稳定运行,那么就需要确保投票能够正常进行,最好不要挂一个节点整个就不work了,所以我们一般要求最少5个节点部署。
注:Observer也完全满足多机房部署的需求
会话是指客户端和ZK服务器的连接,ZK中的会话叫Session
zookeeper是一个类似hdfs的树形文件结构
ZK中的节点不是集群的一台机器,而是数据模型中的数据单元Znode。
悲观锁与乐观锁
悲观锁又叫悲观并发锁,是数据库中一种非常严格的锁策略,具有强烈的排他性。乐观锁认为不同事物访问相同的资源是很少出现干扰的情况,事务处理上不需要进行并发控制,通过对每张表添加一个version字段来实现
版本类型 |
说明 |
version |
当前数据节点数据内容的版本号 |
cversion |
当前数据节点子节点的版本号 |
aversion |
当前数据节点ACL变更版本号 |
Watcher在zookeeper是一个核心功能,watcher可以监控节点的数据变化以及子目录的变化,一旦这些状态发生了变化,服务器就会通知所有设置这个目录节点上的watcher,从而每个客户端很快就知道他所关注内容的变化点并做出相应的反应。
这里强调一次:watch事件(不是数据)!watch事件(不是数据)!watch事件(不是数据)!
ACL是Aceess Control Lists的简写,ZK采用ACL策略进行权限控制,有以下权限:
Follower主要的四个功能
Follower主要的四个功能(1~6):
Follower的消息循环处理有如下几种来自leader的消息:
集群与伪集群的搭建
1) data目录创建myid问题件,里面写一个数字,比如server1就写1,server2就写2
2) zoo_sample.cfg修改为zoo.cfg,修改里面内容
dataDir=xxxx/zookeeper/server1/data
dataLogDir=xxx/zookeeper/server1/dataLog
clientPort=2181
server.1=127.0.0.1:2888:3888 //分别为follower和leader通信端口;选举投票端口
server.2=127.0.0.1:2889:3889
server.3=127.0.0.1:2890:3890
3) 启动2台以上
zkServer.sh start
zkCli.sh –server 127.0.0.1:2182
注:server.X 这个数字就是对应 data/myid中的数字
命令行 |
描述 |
help h |
帮助信息 |
ls / ls /node_1 |
查看当前节点数据 |
Ls2 / |
查看当前节点数据并能看到更新次数等数据 |
stat /node_1 |
查看节点状态信息 字段构成: czxid:创建节点的事务的zxid mzxid:对znode最近修改的zxid ctime:以距离时间原点(epoch)的毫秒数表示的znode创建时间 mtime:以距离时间原点(epoch)的毫秒数表示的znode最近修改时间 version:znode数据的修改次数 cversion:znode子节点修改次数 aversion:znode的ACL修改次数 ephemeralOwner:如果znode是临时节点,则指示节点所有者的会话ID;如果不是临时节点,则为零。 dataLength:znode数据长度 numChildren:znode子节点个数 |
get /node_1 |
获取节点数据 |
create /node_1 123 create -e /node_2 456 create -s /node_3 111 |
格式:create [-s] [-e] path data acl -s 顺序节点(自增系列) -e临时节点 |
set /node_2 22 set /node_2 22 2 |
set path data [version] 修改节点 |
delete /node_2 |
delete path [version] 删除节点(有子节点报错) |
rmr /node_5 |
删除带子节点的节点 |
setquota –n 2 /node_1 |
配额setquota -n|-b val path -n子节点的个数 -b数据的长度 注:配额超出只会有警告日志不报错(zookeeper.out) |
listquota /node_1 |
查看配额 |
|
删除配额delquota [-n|-b] path |
history |
命令历史 |
redo 27 |
重复执行历史的命令 |
|
setAcl path acl c:创建,r:读取d:删除,w:写入a:管理 Scheme的类型:(world,auth,digest,super) setAcl /node1 world:anyone:crdwa getAcl /node1 |
zookeeper自带的客户端是官方提供的,比较底层、使用起来写代码麻烦、不够直接。
org.apache.zookeeper
zookeeper
3.4.6
Curator是Netflix公司开源的一套ZK客户端框架,Curator解决了很多ZK客户端非常底层的细节开发工作,包含连接重连、反复注册Watcher等,实现了Fluent风格的API接口,目前已经成为Apache的顶级项目,是全世界范围内使用最广泛的ZK客户端之一。
org.apache.curator
curator-framework
2.9.0
ZkClient是Github上一个开源的ZK客户端。ZkClient在ZK原生API接口之上进行了包装,是一个更加易用的客户端。同时,zkClient在内部实现了诸如Session超时重连、watcher反复注册等功能。
com.github.adyliu
zkclient
2.1.1
相关源码:
1.性能是有限的
典型的zookeeper的tps大概是一万多,无法覆盖系统内部每天动辄几十亿次的调用。因此每次请求都去zookeeper获取业务系统master信息是不可能的。 因此zookeeper的client必须自己缓存业务系统的master地址。 因此zookeeper提供的‘强一致性’实际上是不可用的。如果我们需要强一致性,还需要其他机制来进行保障:比如用自动化脚本把业务系统的old master给kill掉,但是那会有很多陷阱(这里先不展开这个议题,读者可以自己想想会有哪些陷阱)。
2.选举过程速度很慢
这是一个很难从理论分析上看到的弱点,但是你一旦遇到就会痛不欲生。 前面我们已经说过,网络实际上常常是会出现隔离等不完整状态的,而zookeeper对那种情况非常敏感。一旦出现网络隔离,zookeeper就要发起选举流程。 zookeeper的选举流程通常耗时30到120秒,期间zookeeper由于没有master,都是不可用的。 对于网络里面偶尔出现的,比如半秒一秒的网络隔离,zookeeper会由于选举过程,而把不可用时间放大几十倍。
3.权限控制非常薄弱
在大型的复杂系统里面,使用zookeeper必须自己再额外的开发一套权限控制系统,通过那套权限控制系统再访问zookeeper 额外的权限控制系统不但增加了系统复杂性和维护成本,而且降低了系统的总体性能
当然了,后续也会陆续分享下它作为注册中心时,被大家疯狂吐槽的相关话题。