Zookeeper
Zookeeper
1、概述
1.1什么是Zookeeper
Zookeeper是一个开源的分布式的,为分布式框架提供协调服务的Apache项目,用于管理大型主机。在分布式环境中协调和管理服务是一个复杂的过程。zookeeper通过其简单的架构和API解决了这个问题。ZooKeeper允许开发人员专注于核心应用程序逻辑,不必担心应用程序的分布式特性
1.2Zookeeper的应用场景
- 分布式协调组件
在分布式系统中,需要有zookeeper作为分布式协调组件
- 分布式锁
Zookeeper在实现分布式锁上,可以做到强一致性
- 无状态化的实现
2、搭建Zookeeper服务器
1、zoo.cfg配置文件说明
1 | # ZooKeeper时间配置中的基本单位(毫秒) |
2、Zookeeper服务器的操作命令
1 | 开启Zookeeper服务 ./zkServer.sh start |
3、Zookeeper内部的数据模型
1、zk是如何保存数据的
zk中的数据时保存在节点上的,节点就是znode,多个节点之间构成一棵树的目录结构。
Zookeeper的数据模型是什么样子呢? 他很想数据结构当中的树,也很像文件系统中的目录
树是由节点构成的,Zookeeper的数据存储同样也是基于节点,这个节点叫做Znode
电视不同于书的的节点,Znode的引入方式是路径引入,类似于文件路径
1 | /车/宝马 |
这样的层级结构,让每一个Znode节点拥有唯一的途径就想命名空间一样对不同信息做出清晰隔离
2、zk中的znode是怎样的结构
zk中的znode包含了四个部分:
- data:保存数据
- acl:权限,定义了什么样的用户能够操作这个节点,且能够进行怎样的操作
- c:create创建权限,允许在该节点下创建子节点
- w:write更新权限,允许更新该节点的数据
- r:read 读取权限,允许读取该节点的内容以及子节点的列表信息
- d:delete删除权限,允许删除该节点下的子节点
- a:admin 管理权限,允许对该节点进行acl权限设置
- stat:描述当前znode的元数据
- child:描述当前节点的子节点
3、zk中节点znode的类型
持久节点:创建出的节点,会在回话结束后依然存在,保存数据
持久序号节点:创建出的节点,根据先后顺序描绘在节点之后带上一个数值,越后执行数值越大,适用于分布式锁的应用场景-单调递增
临时节点:临时节点是在会话结束后,自动被删除的,通过这个特性,zk可以实现服务注册和发现的想效果。那么临时节点是如何维持心跳的?
临时序号节点:跟持久序号节点相同,适用于临时的分布式锁
Container节点(3.5.3版本新增):Container容器节点,当容器中没有任何子节点,该容器节点就会被zk定期删除(60s )
TTL节点:可以指定节点的到期时间,到期后被zk定时删除,只能通过配置zookeeper.extendedTypesEnabled=true
4、zk的数据持久化
zk的数据是运行在内存中的,zk提供了两种持久化机制:
- 事务日志
- zk吧执行的命令以日志的形式保存在dataLogDir指定的路径中(如果没有指定的dataLogDir,则按照dataDir指定的路径)
- 数据快照
- zk会在一定时间间隔内做一个内存数据的快照,把该时刻的内存数据保存在快照文件中
- zk通过两种形式的持久化,在恢复时先回复快照文件中的数据到内存中,再用日志文件的数据局做增量恢复,这样的恢复速度更快
4、ZkCli的基本使用
1、多节点类型创建
1 | create /节点名 (节点数据) #增加节点 (结点数据) |
2、查询节点
1 | ls /节点名 #查询该节点下的子节点 |
3、删除节点
1 | delete /节点名 #删除单个叶子结点 |
4、修改节点数据
1 | set 节点路径 "节点数据修改值" 数据版本号(0 1 2 3 4 ……) |
5、权限设置
- 注册当前回话的账号和密码
1 | addauth digest xiaowang : 123456 |
- 创建节点并设置权限
1 | create /test-node adcb auth: xiaowang:123456:cdwra |
倘若一个会话中注册了对这个节点的权限,另一个节点要注册当前会话的账号和密码
5、zk实现分布式锁
1、zk 中锁的种类
- 读锁:大家都可以读,要向上读锁的前提:之前的锁没有写锁
- 我们可以理解为: 读锁就是类似于我们去一家餐厅吃饭,可以一起坐在餐厅里吃饭,但是前提是餐厅暂时不需要装修
- 写锁:只有得到写锁才能写,要想上写锁的前提就是没有任何锁
- 我们可以理解为:餐厅需要装修,但是前提是餐厅没有顾客的时候才能装修,并且我们设定的装修后厨时是不可以装修前台的。
2、zk中如何实现读锁
- 创建一个临时序号节点,节点的数据时read,表示时读锁
- 获取当前zk中序号比自己小的所有节点
- 判断最小节点是否是读锁:
- 如果不是读锁,则上锁失败,为最小节点设置监听。阻塞等待,zk的watch机制会当最小节点发生变化时通知当前节点,于是在执行第二步的流程
- 如果是读锁,则上锁成功
3、zk中如何实现写锁
- 创建一个临时序号节点,该节点的数据是write,表示写锁
- 获取zk中所有的子节点
- 判断自己是否是最小的节点:
- 如果是,则上写锁成功
- 如果不是则说明前面还有锁,则上锁失败,监听最小的节点,如果最小的节点有变化则重新执行第二步
4、羊群效应
如果用上述的上锁方式,只要有节点发生变化,就会触发到其他节点的监听事件,这样的话zk压力很大,——羊群效应,可调整为链式监听解决这个问题
倘若,这时/write0003突然断开连接,那么/read0004则需要去监听read0002,而并非简单的boolen类型监听,只去认为/write0003是否处于阻塞状态
6、zk 的Watch 机制
1、介绍
我们可以吧Watch理解成是注册在特定Znode 上的触发器,一旦这个Znode 发生改变,就会调用create,delete,SetData方法的时候,将会触发Znode上注册的对应时间,请求Watch的客户端会接受到异步通知
具体交互如下:
客户机调用getData方法,watch参数是true,服务端接到请求,返回数据,并且在对应的哈希表里插入被watch的Znode路径,以及Watcher列表
当被Watch的Znode删除,服务端查找哈希表,找到该Znode对应的所有Watcher,异步通知客户端,并且删除哈希表中的对应key-value
客户端使用了NIO通信模式监听服务端的调用
2、zkCli客户端使用watch
1 | create /test xx |
7、Zookeeper的集群实战
1、Zookeeper集群角色
zookeeper集群中的节点有三种角色
- Leader:处理集群的所有事物请求,主要负责写数据,也可以读,集群中只有一个leader
- Follower:只能处理请求,只负责数据的读,也参与Leader 选举
- Observer:只能负责读数据,提升集群读的性能,但不能参与Leader选举
8、ZAB协议
1、什么是ZAB协议
zookeeper作为非常重要的分布式协调组件,需要进行集群部署,集群中会以一主多从的形式进行部署,集群中会以一主多从的形式进行部署,zookeeper为了保证数据的一致性,使用了ZAB(Zookeeper Atomic Broadcst)协议,这个协议解决了Zookeeper的崩溃恢复和主从数据同步问题
2、ZAB协议定义的四种节点模式
- Looking:选举状态
- Following:Follower节点(从节点)所处状态
- Leading:Leader节点(主节点)所处状态
- Observing:观察者节点所处状态
3、选举的中要参数
zookeeper 的 leader 选举存在两个阶段,一个是服务器启动时 leader 选举,另一个是运行过程中 leader 服务器宕机。在分析选举原理前,先介绍几个重要的参数。
- 服务器 ID(myid):编号越大在选举算法中权重越大
- 事务 ID(zxid):值越大说明数据越新,权重越大
- 逻辑时钟(epoch-logicalclock):同一轮投票过程中的逻辑时钟值是相同的,每投完一次值会增加
4、服务器启动时的 leader 选举
1、全新集群选举(第一次启动):
假设目前有三台服务器,分别是1号、2号、3号;
首先1号启动,启动一次选举,1号投给自己一票,由于其他服务器没有启动,无法收到1号的投票信息,此时1号处于Looking(竞选状态);
2号启动,启动选举,2号给自己投一票,并且与1号交换信息,此时1号发现2号的myId比自己投票服务器(服务器1)的myId大,此时1号0票,2号2票,2>(3/2),服务器2的票数最多,超过半数,那么2号当选leader,1号更改状态为following,2号更改状态为leading;
3号启动,启动选举,给自己投一票,此时与之前启动的1号、2号交换信息,此时1号、2号并没有处于Looking(竞选中)状态,不会更改选举状态,3号一票,服从多数,此时3号更改状态为following;
注意:当集群服务器有5台时,前面的服务器1和服务器2,都是LOOKING,服务器1票数为0,服务器2票数为2,当启动第三台服务器时,服务器3的myid大,服务器2会把票数给服务器3,(服务器启动会给自己投一票)这时服务器3票数为3选为Leader,其他的都是follow,之后启动的服务器也是follow;
5、运行过程中的 leader 选举
如果leader服务器挂了,那么整个集群将暂停对外服务,进入新一轮leader选举,其过程和启动时期的leader选举过程基本一致。Leader挂掉后,余下的服务器都将自己的服务器状态变更为looking,然后开始进入Leader选举过程。服务器1号、2号、3号,此时2号是Leader,如果2号停电挂掉之后,1号、3号无法连接到Leader,知道Leader挂了,他们就知道必须选出一个新的 Leader,于是纷纷将自己的状态都修改为 LOOKING 状态:
比如1号的ZXID(事物id)为:77,Epoch(任期代号)为:1,myid(服务器id):1;
3号的ZXID(事物id)为:80,Epoch(任期代号)为:1,myid(服务器id):3;
此时3号为leader。
如果follow挂掉了,此时集群还是可以对外提供服务,挂掉一个是达到整个集群总数的半数以上的,如果挂掉的follow恢复之后,还是以 Follower 的身份加入到集群中来,并且仍然以当前 Leader 的信息来同步,即使它的Epoch大于其他的服务器。
6、zookeeper的心跳检测
在服务器的主从关系之间,是如何知道Leader是否宕机了呢?
在zookeeper集群运行时,leader和Follower会进行日常的通信,同时Observer会在定期进行心跳检测(这个时间也是配置文件中的TickTime,ping一个空的信息到leader查看是否能收到回复),如果超过时长,就默认该Leader宕机了,会推选出新的leader
7、主从节点的数据同步
第二步要先写到自己的数据文件中,才能把数据写到内存中,所以引出一个问题,如果在第三步时出现网络动荡,Leader只将数据写入了左边的服务器而右边的服务器并没有接收到数据,这该怎么办? 实际收到数据的服务器一共有 2个(Leader和其中的一个Follower),整个集群一共3台服务器,由于2/3>0.5所以,可以证明该集群中的网络通信没有问题,但如果有客户端读数据读到那个没有数据的服务器该怎么办呢?这就牵扯到了Zookeeper的数据一致性
8、zookeeper中NIO和BIO的应用
- NIO
- 用于被客户端连接的2181端口,使用的是NIO模式与客户端建立链接
- 客户端开启Watch时,也使用NIO,等待Zookeeper服务器的回调
- BIO:集群在选举时,多个节点之间的投票通信端口,使用BIO进行通信
9、CAP理论
1、CAP定理
一个分布式系统最多只能同时满足一致性,可用性,分区容错性这三项中的两项
- 一致性:“ all nodes see the same data at the same time”,即更新操作成功并返回客户端完成后,所有节点在同一时间的数据完全一致
- 可用性:”Read and writes always succeed” ,即 服务一直可用,而且是正常响应时间
- 分区容错性:”the system continues to operate despite arbitrary message loss or faliure of part of the system”,即分布式系统在遇到某节点网络分区故障的时,仍然能够对外提供满足一致性或可用性的服务。——避免单点故障,就要进行冗余部署,冗余部署相当于是服务的分区,这样分区就具备了容错性
2、BASE理论
BASE理论是对CAP理论的一种延伸,核心思雄昂是即使无法做到强一致性,但应用可以采取适合的方式最终达到一致性
基本可用(Basically Available)
基本可用是指:分布式系统在出现故障的时候,允许损失部分可用性,即保证核心可用
电商大促时,为了应对访问量激增,部分用户可能被引导到降级页面,服务层也只能够提供奖及服务,这就是损失部分可用性的体现
软 状态(Soft State)
软状态是指允许系统存在中间状态,而该中间状态不会影响整体可用性。分布式存储中一般一份数据至少会有三个副本,允许不同节点间副本同步的延时就是软状态的体现。mysql replication的异步复制也是一种体现