赞
踩
大型分布式计算开源的分布式配置服务,同步服务和命令注册。
架构通过冗余实现高可用。
目标:将那些负载且容易出错的分布式一致性服务封装其拉力,构成一个高效可靠的原语集,以一系列简单易用的接口提供给用户使用。
一个典型的分布式数据一致性的解决方案,分布式应用程序可以基于它实现诸如数据发布/订阅、负载均衡、命令服务、分布式协调/通知,集群管理、master选举、分布式锁和分布式队列等。
它提供的名称空间类似标准文件系统,k-v的形式存储。名称key由斜线 / 分割的一系列路径元素,zookeeper名称空间中的每个节点都是由一个路径标识。
CAP理论分布式计算系统来说,不可能同时满足三点。
一个分布式系统最多只能同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance)这三项中的两项。
一致性: 一致性是指数据在多个副本之间是否能够保持一致的特性,等同于所有节点访问同一份最新的数据副本。在一致性的需求下,当一个系统在数据一致的状态下执行更新操作后,应该保证系统的数据仍然处于一致的状态。
可用性: 每次请求都能获取到正确的响应,但是不保证获取的数据为最新数据。
分区容错性: 分布式系统在遇到任何网络分区故障的时候,仍然需要能够保证对外提供满足一致性和可用性的服务,除非是整个网络环境都发生了故障。
在这三个基本需求中,最多只能同时满足其中的两项,P 是必须的,因此只能在 CP 和 AP 中选择,zookeeper 保证的是 CP,对比 spring cloud 系统中的注册中心 eruka 实现的是 AP。
BASE 是 Basically Available(基本可用)、Soft-state(软状态) 和 Eventually Consistent(最终一致性) 三个短语的缩写。
基本可用:分布式系统出现故障,允许损失部分可用性(服务降级、页面降级)。
软状态:允许分布式系统出现中间状态,而且中间状态不影响系统的可用性。
最终一致性: data replications 经过一段时间达到一致性 。
zookeeper中的所有存储的数据由znode组成,节点称为znode,并以key/value形式存储数据。
整体结构类似linux的文件系统模式 以树形结构存储。 其中根路径以 / 开头。
进入zookeeper安装的bin的目录,通过sh zkCli.sh 打开命令行终端,执行 “ls /”命令显示。
[gallery ids="114"]
客户端与服务器之间的连接是基于TCP长连接,client端连接server端默认的2181端口,也就是session会话。
从第一次连接建立开始,客户端开始会话的生命周期,客户端向服务端的ping包请求,每个会话都可以设置一个超时时间。
sessionID:会话ID,用来唯一标识一个会话, 每次客户端创建会话的时候,zookeeper 都会为其分配一个全局唯一的 sessionID 。
timeout:会话超时时间。客户端再构造zookeeper实例时候,向服务端发送配置的超时时间,server端会根据自己的超时时间限制最终确认会话的超时时间。
TickTime:下次会话超时时间点,默认200ms。 在 zoo.cfg 配置文件中配置,便于 server 端对 session 会话实行分桶策略管理。
isClosing:该属性标记一个会话是否已经被关闭,当server端检测到灰灰啊已经超时失效,该会话标记为‘已关闭’,不再处理该会话的新请求。
connecting:连接中,session一旦建立,状态就是connecting状态,时间很短。
connected:已连接,连接成功之后的状态。
closed:已关闭,发生在session过期,一般由于网络故障客户端重连失败,服务器宕机或者客户端主动断开。
leader服务再运行期间定时进行会话超时检查,时间间隔是 ExpirationInterval ,单位是毫秒。 默认值是 tickTime,每隔 tickTime 进行一次会话超时检查。
ExpirationTime 的计算方式:
ExpirationTime = CurrentTime + SessionTimeout; ExpirationTime = (ExpirationTime / ExpirationInterval + 1) * ExpirationInterval;
zookeeper 运行过程中,客户端会在会话超时过期范围内向服务器发送请求(包括读和写)或者 ping 请求,俗称心跳检测完成会话激活,从而来保持会话的有效性。
会话激活流程:
[gallery ids="115"]
激活后进行迁移会话的过程,然后开始新一轮:
[gallery ids="116"]
首先执行命令,打开新的session会话,进入终端。一般这个脚本再zookeeper的bin目录下。
/data/zookeeper/bin/
$ sh zkCli.sh
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]
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 []
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
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
create 命令用于创建节点并赋值
#格式 create [-s] [-e] path data acl [-s] [-e]:-s和-e都是可选的,-s代表顺序节点,注意其中-s和-e可以同时使用,并且临时节点不能再创建子节点。 path:指定要创建节点的路径,比如/mascloud data:要再此节点存储的数据 acl:访问权限相关,默认world,相关于全世界都能访问。 ~# create -s -e /runoob 0 注:创建的节点既是有序,又是临时节点。
set命令用于修改节点存储的数据
#格式 set path data [version] -path:节点路径 -data:需要存储的数据 -[version]:可选项,版本号(可用乐观锁) #只有正确的版本号才能设置成功 set /runoob 0 1 set /runoob 0 2 set /runoob 0 6
delete命令用于删除某节点。
delete path [version] -path:节点路径 -version: 可选项,版本号(同set命令) #实例 ~# ls /runoob ~# delete /runoob/child ~# get /runoob/child (get not exist)
zookeeper支持某些特定的四字命令与其交互, 用户获取 zookeeper 服务的当前状态及相关信息,用户在客户端可以通过 telenet 或者 nc(netcat) 向 zookeeper 提交相应的命令。
安装nc命令: #yum install nc # centos #sudo apt install netcat #ubuntu
四字命令格式:
echo [ command ] | nc [ip] [port]
zookeeper常用四字命令主要如下:
stat命令用于查看zk的状态信息,
~$ echo stat | nc ip port
用于查看当前zkserver是否启动,若返回imok标识正常,
~$ echo ruok | nc ip port
用于列出未经处理的会话和临时节点。
~$ echo dump | nc ip port
用于查看服务器配置
~$ echo cons | nc ip port
用于展示连接到服务器的客户端信息。
~$ echo cons | nc ip port
用于查看环境变量
~$ echo envi | nc ip port
#实例 [zk: localhost:2181(CONNECTED) 2] ls / [runoob, zookeeper] [zk: localhost:2181(CONNECTED) 3] create /runoob 2 Node already exists: /runoob - 注:已存在/runoob节点,再次创建会提示已经存在
#实例 $ ls /data $ create /data/mysql 0 $ create /data/mysql/mysql01 0
$ 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]
$ 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
事件监听机制类似观察者模式,watch流程时客户端向服务端某个节点路径上注册一个watcher,同时客户端也会存储特定的watcher,当节点数据或子节点发生变化时,服务端通知客户端,客户端进行回调处理。特别注意:监听事件被单次触发后,事件就失效。
ls / delete /data [zk: localhost:2181(CONNECTED) 14] delete /data Node not empty: /data # 提示:新版本可以通过deleteall 命令递归删除
最后zookeeper可以应用在不同的经典应用场景
1、数据发布/订阅 2、负载均衡 3、分布式协调通知 4、集群管理 5、master管理 6、分布式锁 7、分布式队列
ACL权限可以针对节点设置相关读写等权限,保障数据安全性。
permissions可以指定不同的权限范围及角色
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
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中,主要依赖ZAB协议来实现分布式数据一致性
ZAB协议分两部分:
消息广播
崩溃恢复
zookeeper使用单一的主进程Leader来接收和处理客户端所有事务请求,并采用ZAB协议的原子广播协议,将事务请求以Proposal提议广播到所有Follower节点,当集群中有过半的Follower服务器进行正确的ACK反馈,那么Leader就会再次向所有的Folloer服务器发送commit消息,将此次提案进行提交。这个过程简称为2pc事务提交,注:Observer节点只负责同步leader数据,不参与2PC数据同步过程。
正常情况消息广播情况下能运行良好,但是一旦Leader服务器出现崩溃,或者由于网络原理导致leader服务器失去了过半 Follower的通信,那么就会进入崩溃恢复模式,需要选举出一个新的leader服务器。这个过程可能会出现两种数据不一致性的隐患,这就需要ZAB协议的特性进行避免。
1、leader服务器将消息commit发出后,立即崩溃
2、leader服务器刚提交proposal后,立即崩溃。
ZAB协议的恢复模式使用策略:
1、选举zxid最大的节点作为新的leader
2、新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:领导者状态
节点启动的时候都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。
当集群中leader服务器出现宕机或者不可用情况时,整个集群无法对外提供服务,进入新一轮的leader选举。
1.变更状态。leader挂后,其它非oberver服务器将自身服务器状态变更为looking。
2.每个server发出一个投票。在运行期间,每个服务器上zxid可能不同。
3.处理投票
4.统计投票
5.改变服务器状态
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。