Zookeeper
一、zookeeper简述
大型分布式计算开源的分布式配置服务,同步服务和命令注册。
架构通过冗余实现高可用。
目标:将那些负载且容易出错的分布式一致性服务封装其拉力,构成一个高效可靠的原语集,以一系列简单易用的接口提供给用户使用。
一个典型的分布式数据一致性的解决方案,分布式应用程序可以基于它实现诸如数据发布/订阅、负载均衡、命令服务、分布式协调/通知,集群管理、master选举、分布式锁和分布式队列等。
1.1 zookeeper数据结构
它提供的名称空间类似标准文件系统,k-v的形式存储。名称key由斜线 / 分割的一系列路径元素,zookeeper名称空间中的每个节点都是由一个路径标识。
1.2 CAP理论
CAP理论分布式计算系统来说,不可能同时满足三点。
一个分布式系统最多只能同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance)这三项中的两项。
一致性: 一致性是指数据在多个副本之间是否能够保持一致的特性,等同于所有节点访问同一份最新的数据副本。在一致性的需求下,当一个系统在数据一致的状态下执行更新操作后,应该保证系统的数据仍然处于一致的状态。
可用性: 每次请求都能获取到正确的响应,但是不保证获取的数据为最新数据。
分区容错性: 分布式系统在遇到任何网络分区故障的时候,仍然需要能够保证对外提供满足一致性和可用性的服务,除非是整个网络环境都发生了故障。
在这三个基本需求中,最多只能同时满足其中的两项,P 是必须的,因此只能在 CP 和 AP 中选择,zookeeper 保证的是 CP,对比 spring cloud 系统中的注册中心 eruka 实现的是 AP。
1.3 BASE理论
BASE 是 Basically Available(基本可用)、Soft-state(软状态) 和 Eventually Consistent(最终一致性) 三个短语的缩写。
基本可用:分布式系统出现故障,允许损失部分可用性(服务降级、页面降级)。
软状态:允许分布式系统出现中间状态,而且中间状态不影响系统的可用性。
最终一致性: data replications 经过一段时间达到一致性 。
二、zookeeper数据模型znode结构详解
2.1数据模型
zookeeper中的所有存储的数据由znode组成,节点称为znode,并以key/value形式存储数据。
整体结构类似linux的文件系统模式 以树形结构存储。 其中根路径以 / 开头。
进入zookeeper安装的bin的目录,通过sh zkCli.sh 打开命令行终端,执行 “ls /”命令显示。
[gallery ids="114"]
三、zookeeper session基本原理
客户端与服务器之间的连接是基于TCP长连接,client端连接server端默认的2181端口,也就是session会话。
从第一次连接建立开始,客户端开始会话的生命周期,客户端向服务端的ping包请求,每个会话都可以设置一个超时时间。
3.1 Session的创建
sessionID:会话ID,用来唯一标识一个会话, 每次客户端创建会话的时候,zookeeper 都会为其分配一个全局唯一的 sessionID 。
timeout:会话超时时间。客户端再构造zookeeper实例时候,向服务端发送配置的超时时间,server端会根据自己的超时时间限制最终确认会话的超时时间。
TickTime:下次会话超时时间点,默认200ms。 在 zoo.cfg 配置文件中配置,便于 server 端对 session 会话实行分桶策略管理。
isClosing:该属性标记一个会话是否已经被关闭,当server端检测到灰灰啊已经超时失效,该会话标记为‘已关闭’,不再处理该会话的新请求。
3.2 session的状态
connecting:连接中,session一旦建立,状态就是connecting状态,时间很短。
connected:已连接,连接成功之后的状态。
closed:已关闭,发生在session过期,一般由于网络故障客户端重连失败,服务器宕机或者客户端主动断开。
3.3 会话超时管理(分桶策略和会话激活)
leader服务再运行期间定时进行会话超时检查,时间间隔是 ExpirationInterval ,单位是毫秒。 默认值是 tickTime,每隔 tickTime 进行一次会话超时检查。
ExpirationTime 的计算方式:
ExpirationTime = CurrentTime + SessionTimeout;
ExpirationTime = (ExpirationTime / ExpirationInterval + 1) * ExpirationInterval;
zookeeper 运行过程中,客户端会在会话超时过期范围内向服务器发送请求(包括读和写)或者 ping 请求,俗称心跳检测完成会话激活,从而来保持会话的有效性。
会话激活流程:
[gallery ids="115"]
激活后进行迁移会话的过程,然后开始新一轮:
[gallery ids="116"]
四、zookeeper客户端基础命令使用
4.1 进入终端
首先执行命令,打开新的session会话,进入终端。一般这个脚本再zookeeper的bin目录下。
/data/zookeeper/bin/
$ sh zkCli.sh
4.2 ls命令
ls 命令查看某个路径下目录列表
#格式
ls path
-- path:代表路径
#实例,查看根目录下的文件。
[zk: localhost:2181(CONNECTED) 0] ls /
[zk, zookeeper, redisExpired, msg-send-task, estask, mascloud, canal-adapter, codis3, disp, otter]
[zk: localhost:2181(CONNECTED) 1]
4.3 ls2 命令
ls2命令用于查看某个路径下目录列表,它比ls命令列出更多的详细信息。
#格式
ls2 path
--path:代表路径
[zk: localhost:2181(CONNECTED) 3] ls2 /mascloud/conf/gw/0/e186cfc2a5ae4ffd89fd736c92e6eb4a
[]
cZxid = 0x90008ae12
ctime = Fri Apr 08 16:30:53 CST 2022
mZxid = 0x90008ae12
mtime = Fri Apr 08 16:30:53 CST 2022
pZxid = 0x90008ae12
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 405
numChildren = 0
#与ls2 区别对比
[zk: localhost:2181(CONNECTED) 4] ls /mascloud/conf/gw/0/e186cfc2a5ae4ffd89fd736c92e6eb4a
[]
4.4 get命令
get命令用于获取节点数据和状态信息
#格式
get path [watch]
-path: 路径
-watch:对节点进行事件监听。
[zk: localhost:2181(CONNECTED) 5] get /mascloud/conf/gw/0/e186cfc2a5ae4ffd89fd736c92e6eb4a watch
{"accessKey":"110210","conn":2,"ecId":"mobanFIF","extProps":{"vipgw":"false"},"flowLimit":1,"flowPeriod":1000,"group":5,"gwId":"e186cfc2a5ae4ffd89fd736c92e6eb4a","host":"192.168.0.31","maxContentBytesForAsc":159,"maxContentBytesForGbk":140,"maxRetryNums":0,"maxSrcIdLength":21,"mtSrcId":"106933355632","ot":false,"port":27881,"protocol":"gw_cmpp_v2.0","secretKey":"123123","share":false,"uniqId":"110210"}
cZxid = 0x90008ae12
ctime = Fri Apr 08 16:30:53 CST 2022
mZxid = 0x90008ae12
mtime = Fri Apr 08 16:30:53 CST 2022
pZxid = 0x90008ae12
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 405
numChildren = 0
4.5 stat命令
stat命令用于查看节点状态信息
#格式
stat path [watch]
-path:路径
-watch:对节点进行事件监听
[zk: localhost:2181(CONNECTED) 10] stat /mascloud watch
cZxid = 0x100003880
ctime = Mon Mar 28 17:02:04 CST 2022
mZxid = 0x100003880
mtime = Mon Mar 28 17:02:04 CST 2022
pZxid = 0xd3016d489e
cversion = 7
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 3
4.6 create命令
create 命令用于创建节点并赋值
#格式
create [-s] [-e] path data acl
[-s] [-e]:-s和-e都是可选的,-s代表顺序节点,注意其中-s和-e可以同时使用,并且临时节点不能再创建子节点。
path:指定要创建节点的路径,比如/mascloud
data:要再此节点存储的数据
acl:访问权限相关,默认world,相关于全世界都能访问。
~# create -s -e /runoob 0
注:创建的节点既是有序,又是临时节点。
4.7 set命令
set命令用于修改节点存储的数据
#格式
set path data [version]
-path:节点路径
-data:需要存储的数据
-[version]:可选项,版本号(可用乐观锁)
#只有正确的版本号才能设置成功
set /runoob 0 1
set /runoob 0 2
set /runoob 0 6
4.8 delete命令
delete命令用于删除某节点。
delete path [version]
-path:节点路径
-version: 可选项,版本号(同set命令)
#实例
~# ls /runoob
~# delete /runoob/child
~# get /runoob/child (get not exist)
五、zookeeper四字命令
zookeeper支持某些特定的四字命令与其交互, 用户获取 zookeeper 服务的当前状态及相关信息,用户在客户端可以通过 telenet 或者 nc(netcat) 向 zookeeper 提交相应的命令。
安装nc命令:
#yum install nc # centos
#sudo apt install netcat #ubuntu
四字命令格式:
echo [ command ] | nc [ip] [port]
zookeeper常用四字命令主要如下:
四字命令使用
stat命令
stat命令用于查看zk的状态信息,
~$ echo stat | nc ip port
ruok命令
用于查看当前zkserver是否启动,若返回imok标识正常,
~$ echo ruok | nc ip port
dump 命令
用于列出未经处理的会话和临时节点。
~$ echo dump | nc ip port
conf命令
用于查看服务器配置
~$ echo cons | nc ip port
cons命令
用于展示连接到服务器的客户端信息。
~$ echo cons | nc ip port
envi命令
用于查看环境变量
~$ echo envi | nc ip port
六、zookeeper节点特性
6.1 同一级节点key名称是唯一的
#实例
[zk: localhost:2181(CONNECTED) 2] ls /
[runoob, zookeeper]
[zk: localhost:2181(CONNECTED) 3] create /runoob 2
Node already exists: /runoob
- 注:已存在/runoob节点,再次创建会提示已经存在
6.2 创建节点时,必须要带上全路径
#实例
$ ls /data
$ create /data/mysql 0
$ create /data/mysql/mysql01 0
6.3 session关闭,临时节点清除
$ ls /data
$ create -e /data/mysql02 0
#实例
#终端一
[zk: localhost:2181(CONNECTED) 12] ls /data
[mysql]
[zk: localhost:2181(CONNECTED) 13] create -e /data/mysql02 0
Created /data/mysql02
#同时终端二查看该节点
[zk: localhost:2181(CONNECTED) 1] ls /data
[mysql, mysql02]
#ctrl+c 关闭终端一连接后,查询终端二/data/mysql02 节点消失
[zk: localhost:2181(CONNECTED) 6] ls /data
[mysql]
6.4 自动创建顺序节点
$ create -s -e /runoob 0
[zk: localhost:2181(CONNECTED) 0] ls /
[data, runoob, zookeeper]
[zk: localhost:2181(CONNECTED) 1] create -s -e /runoob 0
Created /runoob0000000002
[zk: localhost:2181(CONNECTED) 2] create -s -e /runoob 0
Created /runoob0000000003
[zk: localhost:2181(CONNECTED) 3] create -s -e /runoob 0
Created /runoob0000000004
[zk: localhost:2181(CONNECTED) 4] create -s -e /runoob 0
Created /runoob0000000005
6.5 watch 机制,监听节点变化
事件监听机制类似观察者模式,watch流程时客户端向服务端某个节点路径上注册一个watcher,同时客户端也会存储特定的watcher,当节点数据或子节点发生变化时,服务端通知客户端,客户端进行回调处理。特别注意:监听事件被单次触发后,事件就失效。
6.6 delete 命令只能一层一层的删除
ls /
delete /data
[zk: localhost:2181(CONNECTED) 14] delete /data
Node not empty: /data
# 提示:新版本可以通过deleteall 命令递归删除
最后zookeeper可以应用在不同的经典应用场景
1、数据发布/订阅
2、负载均衡
3、分布式协调通知
4、集群管理
5、master管理
6、分布式锁
7、分布式队列
七、zookeeper权限控制ACL
ACL权限可以针对节点设置相关读写等权限,保障数据安全性。
permissions可以指定不同的权限范围及角色
7.1 ACL命令行
- getAcl命令:获取某个节点的acl权限信息
[zk: localhost:2181(CONNECTED) 6] getAcl /zk/codis/db_cmas/proxy
'world,'anyone
: cdrwa
[zk: localhost:2181(CONNECTED) 7] ls /
[zk, zookeeper, redisExpired, msg-send-task, estask, mascloud, canal-adapter, codis3, disp, otter]
- setAcl命令:设置某个节点的acl权限信息
setAcl path acl
- addauth命令:输入认证授权信息,注册时输入明文密码,加密形式保存。
addauth scheme auth
7.2ACL构成
zookeeper的acl通过【scheme:id : permissions】来构成权限列表。
1、scheme:代表采用的某种权限机制,包括world、auth、digest、IP、super几种。
2、id:代表允许访问的用户。
3、permissions:权限组合字符串,由cdrwa组成,其中每个字母代表支持不同权限,创建权限create(c)、删除权限delete(d)、读权限read(r)、写权限write(w)、管理权限admin(a)。
world实例
查看默认节点权限,在更新节点permissions权限部分crwa,结果删除节点失败。
$ getAcl /data/mysql
$ setAcl /data/mysql world:anyone:crwa
$delete /data/mysql
#实例
[zk: localhost:2181(CONNECTED) 36] getAcl /data/mysql
'world,'anyone
: cdrwa
[zk: localhost:2181(CONNECTED) 37] setAcl /data/mysql world:anyone:crwa
[zk: localhost:2181(CONNECTED) 38]
[zk: localhost:2181(CONNECTED) 39] delete /data/mysql
Node not empty: /data/mysql
[zk: localhost:2181(CONNECTED) 44] delete /data/mysql/myslq01
Insufficient permission : /data/mysql/myslq01
auth实例
auth用于授予权限,注意需要先创建用户
$setAcl /data/mysql/mysql01 auth:user1:123456:cdrwa
$addauth digest user1:123456
$setAcl /data/mysql/mysql01 auth:user1:123456:cdrwa
$getAcl /data/mysql/mysql01
[zk: localhost:2181(CONNECTED) 45] setAcl /data/mysql/myslq01 auth:user1:123456:cdrwa
Acl is not valid : /data/mysql/myslq01
[zk: localhost:2181(CONNECTED) 46] addauth digest user1:123456
[zk: localhost:2181(CONNECTED) 47] setAcl /data/mysql/myslq01 auth:user1:123456:cdrwa
[zk: localhost:2181(CONNECTED) 48] getAcl /data/mysql/myslq01
'digest,'user1:HYGa7IZRm2PUBFiFFu8xY2pPP/s=
: cdrwa
[zk: localhost:2181(CONNECTED) 49]
digest实例
退出当前用户,重新连接终端,digest可用于账号密码登陆和验证。
#提示:加密密码是上一步创建的。
$ ls /runoob
$ create /runoob/child01 runoob
$ getAcl /runoob/child01
$ setAcl /runoob/child01 digest:user1:HYGa7IZRm2PUBFiFFu8xY2pPP/s=:cdra
$ getAcl /runoob/child01
$ addauth digest user1:123456
$ getAcl /runoob/child01
[zk: localhost:2181(CONNECTED) 0] getAcl /runoob/child01
Insufficient permission : /runoob/child01
[zk: localhost:2181(CONNECTED) 1] addauth digest user1:123456
[zk: localhost:2181(CONNECTED) 2] getAcl /runoob/child01
'digest,'user1:HYGa7IZRm2PUBFiFFu8xY2pPP/s=
: cdrwa
[zk: localhost:2181(CONNECTED) 3]
IP实例
限制IP地址的访问权限,把权限设置给IP地址为192.168.3.7后,IP为192.168.3.38已经没有访问权限
create /runoob/ip 0
getAcl /ruboob/ip
setAcl /ruboob/ip ip:192.168.3.7:cdrwa
get /runoob/ip
[zk: localhost:2181(CONNECTED) 4] create /runoob/ip 0
Created /runoob/ip
[zk: localhost:2181(CONNECTED) 5] getAcl /runoob/ip
'world,'anyone
: cdrwa
[zk: localhost:2181(CONNECTED) 7] setAcl /runoob/ip ip:10.0.0.200:cdrwa
[zk: localhost:2181(CONNECTED) 8] get /runoob/ip
Insufficient permission : /runoob/ip
八、zookeeper数据同步流程
在zookeeper中,主要依赖ZAB协议来实现分布式数据一致性
ZAB协议分两部分:
- 消息广播
- 崩溃恢复
8.1 消息广播
zookeeper使用单一的主进程Leader来接收和处理客户端所有事务请求,并采用ZAB协议的原子广播协议,将事务请求以Proposal提议广播到所有Follower节点,当集群中有过半的Follower服务器进行正确的ACK反馈,那么Leader就会再次向所有的Folloer服务器发送commit消息,将此次提案进行提交。这个过程简称为2pc事务提交,注:Observer节点只负责同步leader数据,不参与2PC数据同步过程。
8.2崩溃恢复
正常情况消息广播情况下能运行良好,但是一旦Leader服务器出现崩溃,或者由于网络原理导致leader服务器失去了过半 Follower的通信,那么就会进入崩溃恢复模式,需要选举出一个新的leader服务器。这个过程可能会出现两种数据不一致性的隐患,这就需要ZAB协议的特性进行避免。
1、leader服务器将消息commit发出后,立即崩溃
2、leader服务器刚提交proposal后,立即崩溃。
ZAB协议的恢复模式使用策略:
1、选举zxid最大的节点作为新的leader
2、新leader将事务日志中尚未提交的消息进行处理。
九、Zookeeper Leader选举原理
zookeeper的leader选举存在两个阶段,一个服务器启动时leader选举,另一个是运行过程中leader服务器宕机。
- 服务器Id(myid):服务器的唯一标识(SID),通过配置 myid 文件指定,集群中唯一,当ZXID一样时,myid大的节点优先选为Leader ,编号越大在选举算法中权重越大。
- 事务ID(zxid-zookeeper transaction id):每个改变 Zookeeper状态的操作都会形成一个对应的zxid,ZXID最大的节点优先选为Leader。值越大说明数据越新,权重越大。
- 逻辑时钟 (epoch-logicalclock):同一轮投票过程中的逻辑时钟值是相同的,每投完一次值会增加 。
选举状态:
- LOOKing:竞选状态。
- Following:随从状态,同步leader状态,参与投票。
- observing:观察状态,同步leader状态,不参与投票
- leading:领导者状态
9.1 服务器启动时的leader选举
节点启动的时候都looking观望状态,下面就是开始进行选举主流程。以下三台组成集群为例。当几台服务器server启动时,机器之间可以相互通信,进入leader选举过程。
1、每台的server发出一个投票,由于初始情况,server1 和server2都将自己作为leader服务器进行投票,每次投票包含所推举的服务器myid、zxid、epoch,使用(myid,zxid)表示,此时server1投票为(1,0),server2投票为(2,0),然后将各自投票发送给集群中其它机器。
2、接收来自各个服务器的投票。集群中的每个服务器收到投票后,首先判断该投票的有效性,如检查是否是本轮投票(epoch)、是否来自looking状态的服务器。
3、分别处理投票。针对每一次投票,服务器都需要将其它服务器的投票和自己的投票进行对比,对比规则如下:
- 优先比较epoch
- 检查zxid,比较zxid大的服务器优先作为leader
- 如果zxid相同,那么就比较myid,myid较大的服务器作为leader服务器
4、统计投票。每次投票后,服务器统计投票信息,判断是都有过半机器接收到相同的投票信息。server1、server2都统计出集群中有两台机器接收(2,0)的投票信息,此时已经选出了server2为leader节点。
5、改变服务器状态。一旦确定了leader,每个服务器响应更新自己的状态,如果是leader,变更leading。此时server3继续启动,直接加入变更自己为following。
9.2、运行过程中的leader选举
当集群中leader服务器出现宕机或者不可用情况时,整个集群无法对外提供服务,进入新一轮的leader选举。
1.变更状态。leader挂后,其它非oberver服务器将自身服务器状态变更为looking。
2.每个server发出一个投票。在运行期间,每个服务器上zxid可能不同。
3.处理投票
4.统计投票
5.改变服务器状态
版权归原作者 ehuo_ 所有, 如有侵权,请联系我们删除。