Zookeeper学习笔记

0、ZooKeeper安装与集群安装

略。。。

1、Zookeeper介绍

Zookeeper是一个开源的分布式的,为分布式框架提供协调服务的Apache项目。

1.1、Zookeeper工作机制

Zookeeper从设计模式的角度来理解:是一个基于观察者模式设计的分布式服务管理框架,它负责存储和管理大家都关心的数据,然后接收观察者的注册,一旦这些数据的状态发生变化,Zookeeper就将负责通知已经在Zookeeper上注册的那些观察者并做出相应的反应。

1.2、Zookeeper的特点

1、Zookeeper集群:一个领导者(Leader),多个跟随者(Follower)组成的集群。

2、集群中只要有半数以上节点存活,Zookeeper集群就能正常服务。所以Zookeeper适合安装奇数台服务器。

3、全局数据一致:每个Server保存一份相同的数据副本,Client无论连接到哪个Server,数据都是一致的。

4、更新请求顺序执行,来自同一个Client的更新请求按其发送顺序依次执行。

5、数据更新原子性,一次数据更新要么成功,要么失败。

6、实时性,在一定时间范围内,Client能读到最新数据。

1.3、数据结构

ZooKeeper数据模型的结构与Unix文件系统类似,整体上可以看作是一棵树,节点称作一个ZNode。每一个ZNode默认能够存储1MB的数据,每个ZNode都可以通过其路径唯一标识。

1.4、应用场景

应用场景包括:统一命名服务、统一配置管理、统一集群管理、服务器节点动态上下线、软负载均衡等。

1、统一命名服务

在分布式环境下,经常需要对服务/应用进行统一命名,便于识别。

例如:IP不容易记住,而 域名/应用名 容易记住。

以应用名为例,一个应用部署在多个机器上。就可以在zookeeper上记录该应用下有哪些机器。

2、统一配置管理

目的:

分布式环境下,配置文件同步非常常见:

  • 一般要求一个集群中,所有节点的配置信息是一致的,比如Kafka集群。
  • 对配置文件修改后,希望能够快速同步到各个节点。

实现:

ZooKeeper可以通过如下过程实现:

  1. 可将配置信息写入ZooKeeper上的一个Znode。
  2. 各个客户端监听这个Znode。
  3. 一旦Znode中的数据被修改,ZooKeeper将通知各个客户端服务器。

3、统一集群管理

目的:

实时掌握每个节点的状态,并根据节点实时状态做出调整。

实现:

将每个节点的信息写入ZooKeeper上的每一个ZNode。监听这个ZNode可获取它的实时状态。

4、服务器节点动态上下线

将服务器状态信息注册到ZooKeeper并进行监控,服务器节点下线会进行通知。

5、软负载均衡

在Zookeeper中记录每台服务器的访问数,让访问数最少的服务器去处理最新的客户端请求。

2、Zookeeper选举机制

2.1、Zookeeper选举机制-第一次启动

以下面5个服务器进行选举为例:

  • 发起一次选举。服务器1投自己一票。此时服务器1票数一票,不够半数以上(3票),选举无法完成,服务器1状态保持为LOOKING;
  • 服务器2启动,再发起一次选举。服务器1和2分别投自己一票并交换选票信息:此时服务器1发现服务器2的myid比自己目前投票推举的(服务器1)大,更改选票为推举服务器2。此时服务器1票数0票,服务器2票数2票,没有半数以上结果,选举无法完成,服务器1,2状态保持LOOKING;
  • 服务器3启动,发起一次选举。此时服务器1和2都会更改选票为服务器3。此次投票结果:服务器1为0票,服务器2为0票,服务器3为3票。此时服务器3的票数已经超过半数,服务器3当选Leader。服务器1,2更改状态为FOLLOWING,服务器3更改状态为LEADING;
  • 服务器4启动,发起一次选举。此时服务器1,2,3已经不是LOOKING状态,不会更改选票信息。交换选票信息结果:服务器3为3票,服务器4为1票。此时服务器4服从多数,更改选票信息为服务器3,并更改状态为FOLLOWING;
  • 服务器5启动,同4一样当follower。

总结:

服务器得票数达到服务器数量的半数及以上,才能被选举为leader。

在未选取出leader之前:

每个服务器会将票投给当前服务器中myid最大的服务器。得票数超过服务器数量的半数以上即被选举称为leader,其他服务器为follower。

在已经选举出leader之后:

新加入的服务器作为follower。(他自己会投他自己一票,但已经成为leader和follower的服务器不会参与选举)。

2.2、Zookeeper选举机制-非第一次启动

选举机制中的相关概念:

SID:服务器ID。用来标识一台ZooKeeper集群中的机器,每台机器不能重复,与myid一致。

ZXID:事务ID。用来标识一次服务器状态的变更(我感觉是每更新一次,事务ID自增一次)。某一时刻,集群中的每台机器的ZXID值不一定完全一样,因为其中一台机器更新的快一些,而另一台可能跟新的慢一点。

Epoch:每个Leader任期的代号。没有Leader时为同一轮投票过程中的逻辑时终值。(我感觉是每个节点选为Leader后就更新一下这个值,如果某个节点与Leader断开了,那么这个值可能就会很小,在重新选举新Leader是就不优先考虑)

当集群中的Follower节点挂掉了:

如上图中的Server5这个follower节点挂掉之后:

节点在选举新的Leader时,会被告知当前集群有Leader服务器及其相关信息。对于该机器来说,只需要和Leader机器建立练级,并进行状态以及信息的同步即可。

当集群中的Leader节点挂掉了:

如上图中的Server3这个leader节点挂掉之后:

会按照下述规则依次比较其他四个节点的Epoch、ZXID、SID的值:

  • Epoch大的胜出;
  • Epoch相同,ZXID大的胜出;
  • 事务id相同,SID大的胜出;

3、客户端命令操作

3.1、查看当前节点的信息

查看当前节点的子节点:

复制代码
[zk: localhost:2181(CONNECTED) 4] ls /
[zookeeper]

查看当前节点的详细信息:

复制代码
[zk: localhost:2181(CONNECTED) 5] ls -s /
[zookeeper]cZxid = 0x0
ctime = Thu Jan 01 08:00:00 CST 1970
mZxid = 0x0
mtime = Thu Jan 01 08:00:00 CST 1970
pZxid = 0x0
cversion = -1
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 1

其中:

复制代码
cZxid:创建节点的事务 zxid。
ctime:znode被创建的毫秒数(从 1970年开始)。
mZxid:znode最后更新的事务zxid。
mtime:znode最后修改的毫秒数(从 1970年开始)。
pZxid:znode最后更新的子节点zxid。
cversion:znode 子节点变化号,znode 子节点修改次数。
dataVersion:znode 数据变化号。
aclVersion:znode 访问控制列表的变化号。
ephemeralOwner:如果是临时节点,这个是znode拥有者的session id。如果不是临时节点则是0。
dataLength:znode的数据长度。
numChildren:znode子节点数量。

3.2、创建节点

节点类型1-持久/短暂:

持久(Persistent):客户端和服务器端断开连接后,创建的节点不删除。

短暂(Ephemeral):客户端和服务器端断开连接后,创建的节点自己删除。 创建命令加-e参数。

节点类型2-有序号/无序号:

创建znode时设置顺序标识,znode名称后会附加一个值,顺序号是一个单调递增的计数器,由父节点维护。创建命令加-s参数创建有序号节点。

无序号不可创建相同名称的节点,有序号可创建相同名称节点(因为创建有序号节点时会在后面添加不同的序号)。

注意:在分布式系统中,顺序号可以被用于为所有的事件进行全局排序,这样客户端可以通过顺序号推断事件的顺序。

根据上述的类型,节点可分为如下四种:

1、持久化目录节点

创建命令:

复制代码
create /nodepath value

2、持久化顺序编号目录节点

创建命令:

复制代码
create -s /nodepath value

3、临时目录节点

创建命令:

复制代码
create -e /nodepath value

4、临时顺序编号目录节点

创建命令

复制代码
create -e -s /nodepath value

3.3、获取和修改节点值

获取节点的值以及节点详细信息:

复制代码
get -s /nodepath

修改节点的值

复制代码
set /nodepath value

3.4、监听器

1、监听器原理

1、创建一个main()线程;

2、在main线程中创建Zookeeper客户端,这时会创建两个线程:一个负责网络连接通信(connect),一个负责监听(listener)。

3、通过connect线程将注册的监听事件(就是想要监听的内容)发送给Zookeeper服务端。

4、在Zookeeper的注册监听器列表中将注册的监听事件添加到列表中。

5、Zookeeper监听到有数据或者节点变化,就会将这个消息发送给listener线程。

6、listener线程内部调用了process()方法 处理数据或节点发生变化的逻辑。

2、监听器操作

常见的监听:

1、监听节点数据的变化

复制代码
get -w /nodepath

2、监听子节点增减的变化

复制代码
ls -w /nodepath

注册一次只能监听一次,想再次监听需要执行 get -w /nodepath或者ls -w /nodepath命令再次监听。

3.5、节点删除与查看

1、删除节点(删除一个节点,该节点下没有其他节点):

复制代码
delete /nodepath

2、递归删除节点(删除当前节点以及其下所有节点):

复制代码
deleteall /nodepath

3、查看节点状态

感觉这个命令和 ls -s /nodepath的区别是,该命令不显示当前节点下的节点。

复制代码
stat /nodepath

4、客户端API操作

就代码操作了,没啥东西。。。

5、客户端向服务端写数据流程

分为两种情况:

1、客户端写入请求直接发给Leader节点

1、客户端向服务端的Leader节点发送写请求,Leader节点先写一份,然后将数据写给其他Follower节点后收到ack应答。

2、当服务器节点有一半写入成功了,服务端的Leader节点会向客户端发送ack应答。

3、后续会继续向没有进行写入的Follower节点写入数据。

Leader 有针对客户端的写权限,而Follower没有。

2、客户端写入请求直接发给Follower节点

1、客户端向服务端的FollowerA发送写请求,但FollowerA没有处理客户端发送的写权限,因此又将写请求发给了服务端的Leader。

2、服务端的Leader将写请求发送给其他Follower节点,Follower节点写入完成发送ack响应给Leader。

3、当服务端的节点写入完成的数量超过节点总数的一半时,Leader会向FollowerA(客户端请求的Follower节点)发送ack请求。

4、FollowerA收到ack请求后,会向客户端发送客户端ack响应。

5、后续会继续向没有进行写入的Follower节点写入数据。

6、案例实现

6.1、服务器动态上下线监听案例

6.2、ZooKeeper实现分布式锁

6.3、Curator框架实现分布式锁

相关推荐
全职计算机毕业设计3 分钟前
基于Java Web的校园失物招领平台设计与实现
java·开发语言·前端
东阳马生架构9 分钟前
商品中心—1.B端建品和C端缓存的技术文档
java
Chan1611 分钟前
【 SpringCloud | 微服务 MQ基础 】
java·spring·spring cloud·微服务·云原生·rabbitmq
LucianaiB14 分钟前
如何做好一份优秀的技术文档:专业指南与最佳实践
android·java·数据库
面朝大海,春不暖,花不开38 分钟前
自定义Spring Boot Starter的全面指南
java·spring boot·后端
得过且过的勇者y39 分钟前
Java安全点safepoint
java
夜晚回家1 小时前
「Java基本语法」代码格式与注释规范
java·开发语言
斯普信云原生组1 小时前
Docker构建自定义的镜像
java·spring cloud·docker
wangjinjin1801 小时前
使用 IntelliJ IDEA 安装通义灵码(TONGYI Lingma)插件,进行后端 Java Spring Boot 项目的用户用例生成及常见问题处理
java·spring boot·intellij-idea
wtg44521 小时前
使用 Rest-Assured 和 TestNG 进行购物车功能的 API 自动化测试
java