重点
- leader选举规则
- watch事件监听
什么是zookeeper
zookeeper是一种集中式服务,用于维护配置信息,命名,提供分布式同步和提供组服务。
zookeeper使用类似文件操作系统的目录结构树来维护元数据。
zookeeper安装
zookeeper中的三个角色
- leader
leader是整个zookeeper的主节点
负责响应所有对zookeeper状态变更的请求
证集群内部消息处理的FIFO(先进先出)
- follower
响应本服务器上的请求
处理leader的提议
在leader提交该提议时在本地提交
和leader一起构成集群的法定人
参与新leader的选举
- observer
不参与投票
只接受票选结果
不用返回写请求ack
使用时需要修改配置文件
不影响集群的性能
不属于集群的关键角色
断开连接不影响集群可用性
配置软连接
ln -s zookeeper-3.4.14 default
单节点模式
单节点模式,只需要修改配置文件添加日志目录即可(日志目录需要提前创建)
- 修改配置文件
cp zoo_sample.cfg zoo.cfg
vim zoo.cfg
- 修改为下图:
伪分布式模式
伪分布式环境要求
复制多份相同的zookeeper包,创建多个目录并修改配置文件。
目录如下所示:
├── server001
│ ├── data
│ ├── logs
│ └── zookeeper-3.4.0
├── server002
│ ├── data
│ ├── logs
│ └── zookeeper-3.4.0
├── server003
│ ├── data
│ ├── logs
│ └── zookeeper-3.4.0
├── server004
│ ├── data
│ ├── logs
│ └── zookeeper-3.4.0
└── server005
├── data
├── logs
└── zookeeper-3.4.0
- 每个包中的文件夹及内容
伪分布式配置
- 修改配置文件
cp zoo_sample.cfg zoo.cfg
vim zoo.cfg
修改为下图:
注意事项
每个节点端口号都不同(包括启动端口和通信端口)
ip地址相同
- 创建myid文件
在每个包的data文件夹下创建文件myid,文件内容为server后的数值,如server002为2
echo '2' > myid
- 依次启动每个包中的zookeeper
bin/zkServer.sh start
- 查看zookeeper状态
bin/zkServer.sh status
- 出现下面页面说明成功
model的值可以为follower或者为leader都为正常。
环境配置详解
- tickTime
心跳时间。作为zookeeper服务器之间或客户端与服务器之间维持心跳的时间间隔,每个tickTime都会发送一个心跳
- dataDir
zookeeper保存数据的目录,默认将数据的日志文件也卸载这个文件里
- dataLogDir
zookeeper的日志存放目录
- clientProt
zookeeper的端口号,客户机连接zookeeper的端口,zookeeper会监听这个端口,接收客户端请求。
- initLimit
初始化限制时间,初始化时follwer连接leader时的允许等待的心跳数。
- syncLimit
通信限制时间。leader和follwer之间发送消息的最长应答时间(心跳数)
- server.A=B:C:D
A是一个数字表示这个集群的几号机器
B是这个服务器的ip地址
C是该机器与leader通信的端口
D是选举端口,在leader出现问题时,剩余机器进行选举时使用。
zookeeper的端口号
2181:对外通信端口号
2888:leader与follower通信端口号
3888:选举端口号
命令行操作
ls2:查看结点详细信息
create [-e] [-s] /node data :创建<临时><有序>结点,结点需要有数据,默认创建持久结点。
get /node :获取结点数据
set /node data:修改结点
get /node watch:监听结点变化
delete /node: 删除结点
rmr /node:递归删除
stat /:查看结点状态
- czxid:事务id
- ctime-znode:创建时间戳
- mzxid-znode:最后更新的事务id
- mtime-znode:最后修改的时间戳
- pzxid-znode:最后更新的子节点zxid
- cversion-znode:子节点变化号,znode子节点修改次数
- dataversion-znode:数据变化版本号
- aclversion-znode:访问控制列表的变化号
- ephemeralowner:临时节点的session id。持久节点为0。
setAcl:设置权限,需要指定结点,指定权限
getAcl:获取权限
addauth:添加认证用户,切换用户
zookeeper的acl权限控制
acl权限控制类似linux的文件权限
包含三部分
1. 权限模式
2. 授权对象
3. 权限列表
例如: setAcl /node ip:192.168.1.10:crwda //将/node结点的192.168.1.10的权限设置为可增删改查管理权限
- 权限模式
- world:全局模式,所有人,对象只有一种:anyone
- IP:对象是针对固定ip
- auth:对象使用添加认证的用户
- digest:对象使用名密码方式认证的用户
- 权限列表【针对当前节点】
- c:create
- d:delete
- r:read
- w:write
- a:admin
auth授权模式
添加认证用户:addauth digest <suer>:<password>
添加认证授权后可以对该用户进行特殊权限管理。
digest授权模式
添加授权:addauth <path> digest:<user>:<password>:<acl>
该授权模式不用提前进行用户认证。
但是该授权方式的密码需要时加密后的密文格式
密码加密:
echo -n <user>:<password> | openssl dgst -binary -sha1 | openssl base64
超级管理员
zookeeper中存在一个超级管理员用户名是super
该管理员访问任意结点,所有权限。
使用该管理员需要修改zookeeper的启动配置项,添加超级管理员权限。【超级管理员的授权方式是digest授权模式,需要对密码进行加密】
zab协议
zab协议是 ZooKeeper Atomic Broadcast ,zookeeper源自消息广播协议。是保证zookeeper数据一致性的核心算法。是一种通用的分布式一致性算法。
选举规则,宕机数据恢复等等都是通过该协议实现。
zookeeper的选举流程
服务器id
数值越大,权重越高
选举状态- looking:选举状态
- leading:领导状态
- following:跟随状态
- observing:观察状态,不参与投票
事务id
数值越大,数据越新,权重越高
逻辑时钟
投票次数
全新集群选举机制
集群启动时的选举机制。
核心是投票数过半。
【3台服务器的集群】
服务器1启动,投票给自己
将选举结果发送给其他服务器。但是由于没有其他服务器启动,所以没有反馈信息。
服务器2启动,投票给自己
将选举结果发送给其他服务器,服务器1和2交换投票结果,由于2号服务器的数值大权重高,所以服务器1将票投给2号,2号持有两张选票,大于半数。所以服务器2当选leader。状态变为leading。1号状态为following。
如果集群为5台,那么即使2号结果大于1号,也不能选举为leader,因为其选票只有两张。1和2都是looking状态。启动服务器3后,交换选举结果,因为3号的权重更大,所以,1,2都投票给3号,3号当选leader。
服务器3启动,虽然服务器编号大,但是已经存在了leader,所以服务器3直接为following状态。
非全新集群选举机制
当leader宕机后,选举leader的规则
首先统计逻辑时钟是否相同
逻辑时钟即投票次数,如果逻辑时钟小,则说明运行过程中出现过宕机情况。
那么该服务器的选举结果将会被忽略。
比较事务id
事务id越大说明数据越新,运行状态越稳定,权重越大
为什么要设置比较事务这一项?
有可能leader在宕机的时候,follower1接受了一个请求,还没传给leader的时候,leader宕机了,这时为了保证数据的一致性和准确性,所以比较事务id来确定哪个follower是最新的事务。
如果多个follower在leader宕机时都接收到了请求,那么在选举出leader之后,会将请求发送给leader。
如果数据id和逻辑时钟都相同,则比较服务器id
选举规则是为了选取出整个集群中越行最稳定的服务器leader
zookeeper的目录结构
zookeeper的结构非常类似windows文件系统的结构
不同点是文件系统的目录不能存储数据,只能文件存储数据,zookeeper是目录和文件都能存储数据
其实更像树形结构。
zookeeper包含的结点类型
临时结点
临时创建的结点,程序执行完或者会话结束就会消失
临时有序节点
有序排列的临时节点
持久化结点
持久化到本地的结点,程序结束或者会话结束后依然存在
持久化有序结点
有序排列的持久化结点
zookeeper的watch事件监听
zookeeper提供了数据的发布/订阅功能,多个订阅者可同时监听某一特定主题对象,当该主题对象的自身状态发生变化时例如节点内容改变、节点下的子节点列表改变等,会实时、主动通知所有订阅者。
zookeeper采用了 Watcher机制实现数据的发布订阅功能。该机制在被订阅对象发生变化时会异步通知客户端,因此客户端不必在 Watcher注册后轮询阻塞,从而减轻了客户端压力。
watcher机制事件上与观察者模式类似,也可看作是一种观察者模式在分布式场景下的实现方式。
监听内容:
- 结点创建
- 节点删除
- 节点数据修改
- 子节点变更
监听实现步骤
监听机制中包含两个线程,一个连接线程,将监听事件发送给服务端,一个listener监听器接收服务端通知。
- 客户端注册监听事件到服务端。
- 将监听时间保存到服务端的管理列表中。
- 服务端监听所有数据的变化
- 服务器主动通知客户端。
- 客户端收到消息后执行相应的处理逻辑。
监听的特性:
- 一次性,监听触发后会被移除。需要重新注册
- 客户端顺序回调:回调是顺序串行执行
- 轻量级:watchevent监听事件是最小的通信单位,结构上只包含通知状态,事件类型和节点路径。不包含数据内容。
- 时效性:作用范围在session时效内,session失效后快速重连成功,监听事件依然存在。
zookeeper写数据的流程
客户端向服务端发送写数据请求
如果接受请求的服务端不是leader,那么会进一步转发给leader
leader将写请求广播给所有server,follower执行写操作,但不提交
leader收到大多数的server写成功的ack【半数原则】,认为写数据成功
leader发送commit提交广播,follower执行提交操作。此时数据写入完成如果没有半数ack成功返回,超时后写入失败。
类似Innodb的两阶段提交。只不过是innodb是在备库同步时,zookeeper发生在分布式集群中。
leader通知接收请求的服务端写成功
服务端通知客户端写入成功。
zookeeper的读数据不需要经过zookeeper,因为zookeeper每个结点上的数据都是一致的
zookeeper实现动态上下线
zookeeper实现服务动态上下线,实际是使用结点的创建删除与监听机制来完成的。
客户端1用来监听和管理。可以启动一个监听事件,一直监听zookeeper某个目录下的结点。
客户端2服务中运行正常的处理逻辑,除此之外还包括结点注册和运行监听事件,监听自己创建的结点是否存在。
当服务上线时,创建对应的结点。注册成功。
客户端1可以对客户端2执行下线操作,删除客户端2对应结点,客户端2监听到系欸但删除后程序执行退出操作。完成下线。
zookeeper实现分布式锁
zookeeper的一个主要功能是实现分布式系统的数据一致性。
其中重要的是分布式锁的实现。
zookeeper中的锁其实就是一个结点【临时有序结点】。
zookeeper的实现方式是:
一个客户端来获取锁,创建一个临时有序节点。- 判断当前他持有的有序结点是否为最小结点。
- 如果为最小结点,那么获取到锁,执行任务。
- 如果不是最小节点,该客户端会启动watch监听事件,监听比他小的有序节点
- 当他监听的结点被删除之后,说明他之前的客户端已经释放了锁,从而该客户端可以获取到锁
- 判断当前他持有的有序结点是否为最小结点。
- 执行完任务之后,删除临时有序结点。
- 该客户端后的结点监听到节点删除后,获取到锁。
这种实现方式相当于AQS中的独占锁的实现,所有的客户端形成了一个等待队列。
只不过由AQS中的线程唤醒后续结点变成了后续节点监听前置结点。
第三方curator客户端可以实现zookeeper的分布式锁。
锁的种类:
- 分布式可重入排他锁
- 分布式排他锁
- 分布式读写锁
- 多个锁执行一组操作。
- 共享信号量
种类和单体锁的种类类似
zookeeper实现配置中心
设计依靠监听机制实现
1. 将配置信息存储在zookeeper的节点中
2. 客户端在启动时,首先链接zookeeper,然后读取对应节点的信息进行配置
3. 客户端服务启动,并且启动事件监听。监听对应目录的数据变化
4. 变化后,zookeeper会通知客户端,客户端重新加载配置信息。
zookeeper实现分布式唯一id
在分库分表的情况下可以使用临时有序节点来实现唯一id。
但是使用该方法实现有缺陷。zookeeper集群重启后,临时节点将被清除。且存在最大值,会使用完。
curator
curator是奈飞开源的一个zookeeper的客户端。提供给apache。对zookeeper的原生api进行了包装。解决了很多zookeeper客户端非常底层的细节开发。
- zookeeper原生api的不足
- 连接对象是手动控制异步等待。【即手动控制线程等待结点创建】
- 没有超时自动重连机制
- watch只生效一次【可以用递归实现多次】
- 不支持递归创建树形结点。
- curator特点
- 解决session超时重连问题
- watcher自动反复注册
- 简化api
- 提供了分布式锁,共享数据器【唯一id】,缓存机制等。
zooInspector
zooInspector是zookeeper的图形化工具。
taokeeper
淘宝实现的zookeeper的web管理工具。