??理论篇
一、基础概念
ZooKeeper是开源分布式协调服务,提供高可用、高性能、稳定的分布式数据一致性解决方案,通常被用于实现诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master选举、分布式锁和分布式队列等功能。
二、ZooKeeper数据模型
2.1 znode(数据节点)
Zookeeper中所有存储的数据由znode组成,节点也成为znode,并以key value键值对形式存储数据。整体结构类似linux文件系统,根路径以/开头。
znode中数据的读写都是原子的,而且每一个znode都有一个Access Control List(ACL)用来限制谁可以做什么。每一个znode的数据大小不能超过1M
2.1.1 znode数据节点名称规范
- null 字符(即\u0000)不能组成znode节点path的命名
- \ud800 - uF8FF, \uFFF0 - uFFFF, \u0001 - \u001F 以及 \u007F、\u009F 这些玩意无法很好地进行展示,看起来像乱码
- "."可以构成命名的一部分,但是不能单独作为path的命名
- "zookeeper"是保留字
2.1.2 znode数据节点组成:
- stat 状态属性组成:
属性名称 | 属性描述 |
---|---|
czxid | 创建节点的事务ID |
mzxid | 节点最后一次修改的事务ID |
pzxid | 子节点列表最后的一次修改(子节点列表的增加或删除)的事务ID |
ctime | 创建节点的时间,单位:毫秒 |
mtime | 节点最后一次修改的时间,单位:毫秒 |
version | 节点数据变更的次数 |
cversion | 子节点变更的次数 |
aversion | 节点ACL变更的次数 |
ephemeralOwner | 如果节点是临时节点, 则此值为创建该节点的session的id,否则为0 |
dataLength | 节点数据长度 |
numChildren | 子节点个数 |
- data
- children
2.1.3 znode数据节点类型:
持久节点(Persistent Nodes)
临时节点(Ephemeral Nodes) 临时节点的生命周期即为创建这些节点的会话生命周期,即会话结束,则这些节点就会被删除。所以临时节点不允许创建子节点。
顺序节点(Sequence Nodes ) 顺序节点可以是持久的,也可以是临时的。在创建节点时,可为节点路径添加一个单调递增计数器,Zookeeper将通过将10位的序列号附加到原始节点名称后来设置节点路径。
容器节点(Container Nodes) 此类型节点是3.6.0版本之后添加,容器节点是一种有特殊用途的节点,可用于leader选举和分布式锁等,当容器中最后一个子节点被删除,此容器节点将会在未来某个时刻被删除。
超时过期节点(TTL Nodes) 此类型节点是3.6.0版本之后添加,当创建一个持久节点或者顺序持久节点时,可以为其设置一个毫秒级的超时过期时间,如果在设置时间内,此节点没又被修改过而且也没有子节点,则此节点将作为候选项,在未来某个时刻被删除。当然TTL Nodes默认是禁用状态的。
三、Zookeeper Time
Zookeeper中时间有很多表示时间的方式。
Zxid 事务ID。Zookeeper状态的每次变化都会收到这样一个事务ID
Version numbers
Ticks
Real time
四、ZooKeeper Sessions (会话)
Zookeeper客户端通过
五、ZooKeeper Watches (监听)
5.1 watch基本概念
Zookeeper所有读相关操作:getData()、getChildren()、 exists()等都有一个参数boolean watch用来设置watche。按照读的内容不同,有两种watch:Data Watch和Child Watch,像getData()和exists()这种属于读取znode数据,所以属于Data Watch,所以当znode数据发生变更,将触发znode的Data Watch;getChildren()对应的就是Child Watch。创建子节点将触发父节点的Child Watch,而节点的删除将同时触发Data Watch和Child Watch。
Watch是一个一次性触发器,比如当调用 getData("/znode1", true) 后--true代表设置监听,该节点被删除或者数据发生变更,将会触发客户端注册的watch,触发之后,将被删除,也就是往后数据再变化就不会再触发此watch了。
5.2 watch 事件类型
那么当触发watch的时候有因为数据发生变化的,有因为节点创建或删除的等等,客户端如何判断服务端触发的watch是各种类型呢?zookeeper提供了EventType的枚举,服务端触发watch时,会告诉客户端是何种类型。
一共有如下这么多事件类型:
- None
- NodeCreated
- NodeDeleted
- NodeDataChanged
- NodeChildrenChanged
- DataWatchRemoved
- ChildWatchRemoved
- PersistentWatchRemoved
其中最后三个事件类型:DataWatchRemoved、ChildWatchRemoved、PersistentWatchRemoved分别是删除不同类型的watch的时候事件类型,从单词字面意思也应该能够理解。
5.3 永久递归watch
3.6.0之后(包括3.6.0) 客户端可以通过addWatch()为znode设置永久、递归的watch,这意味着watch不再是一次性的了,可以多次触发不会被删除,并且还会递归触发。当然也有移除永久watch的机制:removeWatches()
watch是维护在zookeeper服务端的,所有当客户端与服务端断链,将不会接受到watch的触发,而当重连后都将恢复可以重新触发。
5.3 关于watch的一些注意事项?
1.标准watch是一次性的,如果当客户端接收到watch的回调通知,那么此watch将被删除,如果客户端还想接收到通知,则需要注册另一个watch
2.正如第一条所讲,在客户端接收到watch回调通知时,可能会继续设置一个watch以监听znode的下次变更,但是假如在接收到watch和发送请求设置新watch的中间,znode发生了多次变化,这个可能客户端会接收不到此变更通知。
3.如果为比如exist、getData注册了同一个watch,那么当watch被删除的时候,仅会触发一次delete watch事件
六、ZooKeeper access control using ACLs(权限控制器)
ACL全称Access Control List,即访问控制列表。Zookeeper的ACL实现很类似与UNIX的文件系统权限控制。每一个ACL针对指定的znode,但是并不针对指定znode的子节点,也就是ACL并不递归生效。假如给/app设置了一个ACL,那么/app/childtest将不受此ACL控制。
权限的表达式为scheme:id, permissions
6.1 scheme-->授权策略
授权策略一共有4种
授权策略 | 含义 |
---|---|
world | 默认策略。任何人都可以访问 |
auth | 即已经认证通过的用户 |
digest | 通过使用MD5进行哈希 username:password格式生成的字符串来进行身份验证,当进行身份验证时,是使用usename:password明文形式字符串,当用做ACL验证时,会先经过base64编码,然后使用SHA1加密 |
ip | 使用客户端IP作为ACL身份标识。其格式为addr/bits,bits代表客户端的IP地址要至少匹配ACL中IP地址的多少位 |
x509 |
6.2 id-->授权对象
6.3 permissions-->权限点
权限点 | 含义 |
---|---|
CREATE | 可以创建子节点 |
READ | 可以获取znode数据,以及znode的子节点列表 |
WRITE | 可以为znode设置数据 |
DELETE | 可以删除znode的子节点 |
ADMIN | 可以为znode设置ACL,ADMIN就像是znode的owner |
六、ZooKeeper Consistency Guarantees(一致性保障)
Zookeeper是高性能、可扩展的服务,它的读操作和写操作都非常的快
6.1 Sequential Consistency(顺序一致性)
来自客户端的更新将会按照顺序进行处理
6.2 Atomicity (原子性)
6.3 Single System Image(单一系统镜像)
无论客户端连接到哪一个服务器上,其看到的服务端数据模型都是一致的
6.4Reliability(可靠性)
一旦更新请求被处理,更改的结果将会持久化
6.5 Timeliness (及时性)
??实战篇
一、下载安装
1.1 下载
下载地址:https://zookeeper.apache.org/releases.html#download [apache-zookeeper-3.6.2-bin.tar.gz](https://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper/zookeeper-3.6.2/apache-zookeeper-3.6.2-bin.tar.gz)
1.2 单机模式
1.2.1 设置配置文件
在conf目录下会有一个zoo_sample.cfg文件,这里提供了样例配置信息,我们只需要将此文件改名为zoo.cfg,这样才会被zookeeper识别。该配置文件中的配置项说明:
tickTime 单位:毫秒。是服务器之间或客户端与服务器之间维持心跳的时间间隔;且最小会话超时时间将是tickTime的两倍
dataDir zookeeper保存的数据的目录地址,默认情况下,事务log也会记在这里(除非另外指定)
clientPort 客户端连接服务端的端口 zoo.cfg示例
tickTime=2000
dataDir=/var/lib/zookeeper
clientPort=2181
1.2.2 启动zookeeper服务端(前提是需要保证安装机器上有JDK)
./zkServer.sh start
1.2.3 客户端连接服务器
./zkCli.sh -server 127.0.0.1:2181
1.3 集群模式
zookeeper集群部署可以获得高可靠性,要想实现高可靠容错好集群,至少需要3台服务器,且集群数量最好为奇数。
1.3.1 设置集群配置文件zoo.conf
tickTime=2000
dataDir=/var/lib/zookeeper/
clientPort=2181
initLimit=5
syncLimit=2
server.1=zoo1:2888:3888
server.2=zoo2:2888:3888
server.3=zoo3:2888:3888
除了单机模式中需要配置的那几个参数外,需要配置和集群相关的参数
- initLimit 表示集群中的followers服务器 在连接leader服务器时,经过最大initLimit个tickTime后,若leader还未接收到followers的信息,则认为连接失败
- syncLimit 表示集群中follower服务器与leader服务器在同步消息时最大syncLimit*tickTime时间间隔未收到响应,则此follower会被抛弃
- server.id=host:port:port 配置文件中每行的server.id=host:port:port共同组成一个集群。这里有两个端口,前面的端口用于与集群leader连接的端口,后面的端口用于leader选举。如果想在同一台机器上搭建伪集群,则第一个端口不同即可
1.3.2 设置myid文件
myid文件中只有一行内容,且这行内容就是上述配置server.id=host:port:port 中的id,在集群模式下该id不可重复,范围为1-255,将此文件放在dataDir参数表示的目录下
1.3.3 查看服务器状态
./zkServer.sh status
1.3.4 搭建集群过程遇到的问题
在搭建集群的时候,启动三台机器都显示启动成功,但是使用客户端命令也连接失败,通过./zkServer.sh status 显示Error contacting service. It is probably not running.查看logs