zookeeper的介绍和使用

一.概念

1.1 官网

https://zookeeper.apache.org/

在这里插入图片描述

1.2 作用

  1. 配置管理:ZooKeeper可以轻松地满足分布式集群共享配置。ZooKeeper一旦某个节点的配置信息发生变化,可以通知到其他各个节点进行相应的动作。
  2. 分布式锁:在分布式计算中,会有许多任务需要对资源进行排他性访问。这就需要使用到分布式锁。ZooKeeper的znode能够直观高效地实现分布式锁。
  3. 集群管理 :ZooKeeper能够探测出节点失效情况。一旦有节点失效,ZooKeeper将会立刻选举新的节点来替代。
  4. 负载均衡:在分布式系统中,一个完备的处理请求的体系,就必须要有负载均衡机制,通过ZooKeeper可以轻松实现。
  5. 数据一致性:ZooKeeper保证了在一个时间点上,无论访问哪个ZooKeeper节点,都能读取到同样的数据。
  6. 命名服务:在分布式系统中,通过使用IP:Port的方式来标识一个唯一的服务会带来很多困扰。使用ZooKeeper能够为繁多的服务提供统一的命名服务,方便服务的发现和调用。

1.3 解决什么问题(zookeeper诞生)

1.leader肯定会挂
2.服务不可用
3.不可靠的集群
4.事实,zk集群及其高可用
5.如果有一种方式可以快速的回复出一个leader

1.4 短暂的节点

在 Zookeeper 中,存在一种叫做"短暂节点"(Ephemeral Nodes)的概念。短暂节点是一种特殊类型的节点,其生命周期绑定到创建它的会话(Session)。当会话结束时,短暂节点会被自动删除。

当我们在分布式环境中需要临时存储某些数据,或者追踪分布式环境中某个或者某类实体的存在状态时,短暂节点非常有用。这个特性在实现分布式锁、服务发现、集群管理等功能上特别有价值。

例如在集群管理中,每个服务器节点启动后都在 Zookeeper 上创建自己的一个短暂节点,如果有服务器节点宕机,对应的短暂节点将会消失,这能够让 Zookeeper 以及其他节点知道某个服务器节点失去联系。

同样的,在分布式锁的使用场景中,短暂节点的存在表明锁被占用,短暂节点的消失则表示锁已被释放,这样就可以方便其他节点知道何时可以去获取锁了。

zk 节点存储的数据不多 (1M)

二.zk的使用

2.1 zookeeper的安装

因为zk是java语言写的 ,所以zk依赖与jvm环境,在此之前

需要先准备好jdk

2.1.1 jdk8安装 并且配置环境变量 (linux版)

在这里插入图片描述

tar -xvf jdk-8u333-linux-x64.tar.gz
mv jdk1.8.0_333 java8
vim /etc/profile
	export JAVA_HOME=/usr/local/src/java8
	export PATH=$PATH:$JAVA_HOME/bin
source /etc/profile

安装成功如下

在这里插入图片描述

2.1.2 zookeeper安装并且配置环境变量 (linux单机版)

tar -xvf zookeeper-3.4.6.tar.gz
mv zookeeper-3.4.6 zk
cd zk/conf

cp zoo_sample.cfg zoo.cfg
cd ../bin/
2.1.2.1 zookeeper启动

进入 到bin目录

在这里插入图片描述

可以看到 启动|日志形式启动 | 停止 | 重启…

在这里插入图片描述

启动后

在这里插入图片描述

2.1.3 集群的搭建

参考 https://blog.csdn.net/yaxuan88521/article/details/128127423

2.2 zk客户端

zkCli.sh 客户端 (不加客户端默认会连接自己)

连接成功后可以使用help 命令查看 指令

在这里插入图片描述

ls / --查看 根目录(因为zk本来就是以文件,文件夹存储的)

create /test “” 在根目录下创建 一个test

在这里插入图片描述

create /test/test01 “”

[zk: localhost:2181(CONNECTED) 8] set /test/test01 "hellozk"
cZxid = 0x7
ctime = Fri Oct 13 04:25:29 EDT 2023
mZxid = 0x8
mtime = Fri Oct 13 04:27:39 EDT 2023
pZxid = 0x7
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 9
numChildren = 0


[zk: localhost:2181(CONNECTED) 9] get /test/test01
"hellozk" (这里最多可以放1M数据,而且是二进制安全的)
cZxid = 0x7
ctime = Fri Oct 13 04:25:29 EDT 2023
mZxid = 0x8
mtime = Fri Oct 13 04:27:39 EDT 2023
pZxid = 0x7
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 9
numChildren = 0

从上面看 除了数据之外还有,cZxid,ctime,…等等

那么这些是什么意思呢 (集群模式下)?

cZxid = 0x200000004 2代表了第二次成为主机0x2(前32位) --会增  
					后00000004(32位)代表的是事务
ctime = Sun Feb 26 21:18:53 EST 2023  --创建时间
mZxid = 0x200000005 --修改节点的事务id
mtime = Sun Feb 26 21:18:57 EST 2023 --修改时间
pZxid = 0x200000004  --当前节点下最后创建的id号
这里举个栗子 从00000001开始
	首先创建了一个 test ==>pZxid = 0x100000001
	在test下载创建一个test01 ==> pZxid = 0x100000002
	在test下载创建一个test02 ==> pZxid = 0x100000003
	图例在下
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0 --临时节点 可以用 create -e /xxoo 创建    客户端断开时候就会消失
dataLength = 7
numChildren = 0
在每次 关闭掉客户端后 cZxid事务id会增加 1, 原因是要删除会话 这一个事务
create -s /xxxx/xxxx   在分布式下,不同的客户端 节点不一样。为了区分 健重复问题

dataVersion	当前节点版本号(每修改一次值+1递增)
cversion	子节点版本号(子节点修改次数,每修改一次值+1递增)
aclVersion	当前节点acl版本号(节点被修改acl权限,每修改一次值+1递增)
ephemeralOwner	临时节点标示,当前节点如果是临时节点,则存储的创建者的会话id(sessionId),如果不是,那么值=0
dataLength	当前节点所存储的数据长度
numChildren	当前节点下子节点的个数

pzid 图例

在这里插入图片描述

2.3 zk集群中端口的作用

端口 3888 选举投票用的
端口 2888 leader 接收writer请求

三.zk的分布式配置管理

3.1统一配置管理:

每个应用节点都可以把配置信息存储在ZooKeeper的一个ZNode(ZooKeeper Node的缩写)节点上。之后若有配置信息需要修改,只需要修改这个ZNode的信息即可。其他应用节点则可以设置对这个ZNode的监听(watch /path ),一旦这个ZNode的信息有变动,所有监听它的应用节点就会收到通知,从而得知配置信息有所改动,可以去获取新的配置。

这样就避免了应用节点存储配置信息,修改配置也只需要在一个地方修改。所以配置统一管理在ZooKeeper中就是利用ZNode以及监听机制来实现的。

你需要注意的是,对于ZNode节点的读操作尽量精简,因为过多的读操作会增加ZooKeeper的负载,影响性能。因此,通常采取的方法是将配置信息缓存在本地,当接收到ZNode数据变更的通知后,再去读取新的配置信息。

3.2分组管理:

ZooKeeper同样可以使用ZNode来实现分组管理。比如你有很多相同的服务节点,现在想把这些服务节点进行分组。那么你可以创建一个ZNode作为父节点,然后下面创建多个子节点,每个子节点对应一个组,子节点下再创建子节点,对应每个服务节点。这样服务节点就按照ZNode的组织形式进行了分组。

3.3统一命名:

ZooKeeper的ZNode提供了树状的命名空间,并且ZNode的全路径名唯一,这样可以利用ZNode的全路径名来实现资源的统一命名。比如对于同样的服务节点,你可以把它们的统一名称作为ZNode的路径来保存,然后通过ZNode的路径就可以找到这个服务。

3.4数据同步问题:

在ZooKeeper中,所有的写操作,像create,delete,setData等,都会体现在整个ZooKeeper集群中,保证数据的一致性。ZooKeeper通过Zab协议来保证数据的一致性。客户端向任意一个ZooKeeper服务发送写操作,该服务将会向其他ZooKeeper服务转发这个请求,只要这个请求得到过半数的ZooKeeper服务接收,那么就算这个写操作完成。

如果是读操作,比如getData,exists等,客户端只会向与它连接的那个ZooKeeper服务发出请求。因为所有ZooKeeper服务保存的数据都是一致的,ZooKeeper通过适应性的读取一致性策略,保证在不同的场景下,读操作的一致性。

3.5 分布式锁

ZooKeeper 分布式锁的执行原理:

设置:
假设我们有一个名为 /_locknode_ 的锁节点,任何客户端都想在其中创建子节点以获取锁。

步骤:

  1. 每个想要获取锁的客户端进程尝试在 /_locknode_ 路径下创建一个临时顺序节点。

  2. 客户端获取当前 /_locknode_ 下所有子节点的列表,然后查看自己创建的节点在其中的位置。如果在所有节点中,自己创建的节点序列最小,那么它就认为自己已经获取到了锁。

  3. 如果客户端的节点不是序列最小的节点,它会将自己监听至比他的节点序列小的那个节点。例如,如果客户端创建的节点序列为 locknode/0000000003,那么他将会监听 locknode/0000000002

  4. 当一个客户端释放锁(删除自己的节点)后,ZooKeeper会通知监听在此节点上的所有其他客户端,这样子序列中的下一个节点就知道原来的节点已经释放了锁,它就可以再次验证是否可以获取锁(因为在此过程中可能有新的节点创建,所以需要再次验证)。

  5. 在这个过程中,如果有任何一个客户端死亡(进程停止,网络问题等),那么它在 /_locknode_ 下创建的节点也会被清除,从而它持有的锁(如果有的话)也会被释放。

ZooKeeper 分布式锁的设计原理是典型的 “谁先到谁先得” 机制,取决于 ZooKeeper 的特性(保证了每个创建的节点序列号的唯一和递增)以及 “watcher”(监听器)机制(允许客户端监听某个节点的变化)。当最小序列节点被删除(即锁被释放)时,只有序列号次小的节点收到通知,从而避免了"羊群效应"。

3.6 zookeeper的Watch监控

ZooKeeper 的 Watch 监控:

ZooKeeper Watch 是一个简单的事件通知机制。当客户端对一个 ZooKeeper 节点(znode)设置了 Watch,然后这个节点发生了某种特定类型的变化时,ZooKeeper 会给客户端发送一个通知。例如,一个客户端可能对一个 znode 的数据更改设置了 Watch,如果另一个客户端更改了这个 znode 的数据,那么第一个客户端会得到一个通知。

ZooKeeper 的 Watch 有些特殊性质:

  1. 一次性:一旦触发,Watch 就会被移除。如果你要继续保持观察,需要重新设置 Watch。
  2. 有序性:对于一个特定的 Watcher 和 znode,Watch 通知保证以他们被触发的顺序发送。

心跳机制:

心跳机制通常用于检查一个网络组件是否还活着,或者检查网络连接是否仍然存在。在一个分布式系统中,节点之间经常需要发送心跳信息,以确定其他节点是否仍然活着。

心跳消息通常是定期发送的,时间间隔固定。如果在一个定期的时间间隔内没有收到一个节点的心跳消息,那么其他节点可能会从系统的活动节点列表中移除这个节点,然后执行其他的恢复或者重新分配的机制。

Watch和心跳的区别:

  1. 触发条件不同:Watch是基于节点事件变化的,只要节点有数据变更或者被删除,Watch就会被触发;而心跳则是定期发送,用于检测节点的存活状态。

  2. 使用场景不同:Watch主要用于节点变化的通知,典型的应用场景比如配置信息的动态更新,集群的负载均衡等;而心跳则主要用于检测节点存活,用于节点的选举,故障恢复等。

  3. 信息量不同:Watch因为是基于节点事件的,所以它会带有事件的详细信息;而心跳只是简单地确认一下对方是否还活着,信息量相对较小。

  4. 实时性不同:一般来讲,Watch可以看做几乎实时的,因为它是基于事件触发的;而心跳的实时性取决于心跳的周期,如果周期设置得较长,可能会出现检测延迟的问题。

四.zk的安装和集群配置

1.安装jdk 在第二点中有提及

2.安装zookeeper 解压

  1. 具体步骤
cd /*(你zookeeper的目录)*/conf/
cp zoo.simple.cfg zoo.cfg --改名字
vi zoo.cfg --编辑配置文件 加上下面的配置
server.1=node01(ip/主机名):2888:3888
server.2=node02(ip/主机名):2888:3888
server.3=node03(ip/主机名):2888:3888
server.4=node04(ip/主机名):2888:3888
mkdir -p /**/**/** --这里是创建配置文件中data目录的
cd /**/**/**
vi myid -- 对应server.1 中的 1 
cd /opt
scp -- 远程发送到其他主机 
mkdir -p /**/**/**
echo 2 |  3 | 4  > /**/myid  --同理  
vi /etc/profile  --配置环境变量
export ZOOKEEPER_HOME=/**/zookeeper
export PATH=$PATH:$JAVA_HOME/bin:$ZOOKEEPER_HOME/bin
source  /etc/profile

-- 注意,此处代码并不能直接复用 只是一个搭建集群的大概过程 ,如果需要查看集群如何搭建
    请跳转到 2.1.3

五.zk分布式协调

5.1 拓展性

Apache ZooKeeper是一种分布式坐标服务,它可以为大型分布式系统提供高效且可靠的分布式坐标功能,比如:配置维护、域名服务、分布式同步、分布式锁等。

在 ZooKeeper 中并不具体细分每个 ZooKeeper 服务实例的角色,而是定义了它们是如何协同工作的。ZooKeeper 集群是由若干个服务实例通过网络相互连接,共同提供服务的,这些实例统称为 ZooKeeper 服务器(ZooKeeper Server)。他们共同维护着 ZooKeeper 的状态,并通过这些状态提供 ZooKeeper 的各项服务。我们可以把一个ZooKeeper集群看作是一个整体,为客户端提供服务。

在所有的 ZooKeeper 服务器中,有一类特殊的服务器,被称为 Leader,其他服务器被称为 Follower。这种角色主要是为了在实现强一致性的过程中,协调各个服务器之间的工作。

  1. Leader(领导者): 在整个 ZooKeeper 集群中,同时只会有一个 Leader。这个 Leader 是通过 ZooKeeper 的选举机制 from the ZooKeeper ensemble。所有客户端请求的写操作都会经过 Leader 服务器进行处理,它代表整个 ZooKeeper 集群对外提供服务。它还负责在写操作时与其他服务器进行均衡,保证集群的强一致性。

  2. Follower(跟随者): Follower 服务器可以处理客户端的读请求,写请求则会转给 Leader 服务器处理,并参与到写操作的过程中来保持数据的强一致性。同时,Follower 还参与 Leader 服务器的选举。

当然,也有一个Observer角色,主要用于读密集的系统:

  1. Observer(观察者): Observer服务器的角色与Follower服务器相似,都可以处理客户端的读请求,但是在写操作中,它不参与投票过程,只从 Leader 服务器那里接收最新的数据状态, 而不参与写操作的投票过程。 Observer 的存在可以在不影响写性能的情况下增加集群的读性能和系统的扩展性。
zoo.cfg
server.1=node01:2888:3888
server.2=node02:2888:3888
server.3=node03:2888:3888
server.4=node04:2888:3888 observer

当 Leader 服务器出现故障或者无法服务的时候,Follower 服务器就会通过投票选举出一个新的 Leader,以保证 ZooKeeper 服务的高可用。

5.2 可靠性

5.2.1 快速恢复leader

ZooKeeper 集群中的 leader 节点发生故障,ZooKeeper 会自动进行新的 leader 选举,一旦新的 leader 被选出,整个集群会快速恢复正常运作。

5.2.2 最终一致性

  1. **全局有序:**ZooKeeper 会给每一个更新操作(例如变动数据或节点)分配一个递增的事务id (zxid)。所有的更新请求在一个客户端看到的顺序就是他们被 ZooKeeper 应用的顺序,即他们的 zxid 递增的顺序。这样就保证了所有客户端看到的 ZooKeeper 状态一致。

  2. **原子性:**更新操作要么完全执行,要么完全不执行。也就是说,即使在系统发生网络分区、服务器崩溃等情况下,ZooKeeper 中的所有客户端在任何时刻看到的都是一致的系统状态。

  3. **FIFO 的客户端顺序:**由同一个客户端发出的请求,ZooKeeper 会按照 FIFO(先进先出)的顺序来处理。

  4. **可靠性:**一旦一个更新操作在 ZooKeeper 之中完成,这个更新操作的结果将被永久存储,直到有新的更新来覆盖它。

  5. **副本同步:**ZooKeeper 通过选举机制选出一个 leader,所有的写操作都会先在 leader 上进行,然后再复制到其他的 follower 上。只有当半数以上的 follower 收到了更新信息,写操作才算完成。

5.2.3 Paxos

更详细参考 https://www.douban.com/note/208430424/?_i=7481426ATQpdPy,7353743mK3o0B2

Paxos是一种计算机科学中的一种分布式一致性算法。在理想与非理想网络环境中,Paxos能够保证系统的一致性。这个算法由Leslie Lamport在1990年提出。

Paxos算法主要解决的问题是,在一个可靠的系统中如何达成一致的决策。这种问题在分布式系统中非常常见,比如说,一个集群中的所有节点需要决定采用哪个值作为参数。

Paxos算法主要包括三个角色:

  1. Proposer(提议者):开始一个提议请求,其提议必须包含一个提议号和提议值。

  2. Acceptor(接受者):接受或拒绝提议者提出的提议。

  3. Learner(学习者):学习被接受的提议的结果。

Paxos算法的基本流程为:

  1. Proposer向Acceptor提出提议。每个提议都有一个唯一的编号**(Zxid)**,Proposer可以向一个或者多个Acceptor提出提议。

  2. Acceptor在收到提议后,可以选择接受或者拒绝。如果这是Acceptor收到的第一个提议,或者是编号最高的提议,Acceptor会接受这个提议。

  3. 如果Acceptor接受了提议,它会将这个信息发送回Proposer,同时也会发送给Learner。

  4. 如果Proposer发现其提议被大多数**(过半)**Acceptor接受了,那么此提议的一致性协议过程就完成了,Proposer将会通知所有的Learner提议的结果。

  5. Learner从Proposer或Acceptor那获取决议结果,以便可以学习决策状态。

Paxos算法被广泛应用于多数分布式一致性系统中,如Google的Chubby锁服务,Apache的ZooKeeper。

5.2.4 ZAB

ZAB是Zookeeper Atomic Broadcast(Zookeeper原子广播)的缩写,它是Apache Zookeeper项目的核心组件之一。Zookeeper是一个为分布式应用程序提供一致性服务的开放源码项目。它通过提供一个简单的接口,能帮助开发者设计出基于复制的高可用性服务。复制,从本质上讲,就是在多个主机之间保持数据一致性,也就是分布式系统中的共识问题。

ZAB协议是Zookeeper解决分布式一致性问题的关键,它主要负责在所有的Zookeeper 服务器中为客户端提供一个单一的系统视图,即无论客户端连接到哪一台Zookeeper服务器,显示出来的系统数据都是一致的。

ZAB协议包含了两个主要模式:

  1. 崩溃恢复模式(恢复模式):如果某个领导者崩溃,就会导致系统无法对客户端请求做出响应,此时需要选举出新的领导者并完成崩溃恢复,以保证整个系统仍能恢复并正常运行。

  2. 广播模式(消息传递模式):在这个模式下,领导者将更新请求广播到所有的跟随者。所有的服务器都将按顺序执行相同的操作,从而保证了分布式系统的一致性。

ZAB作用在可用状态并且有leader

1.从机创建节点
2.发送到leader
3.数据放到内存中 日志存到磁盘中

4.向从机发送日志数据。
5.从机反馈数据。
6.加上leader过半数同意
7.leader向从机发送writer指令 --写入磁盘
8.同步完后向从机发送成功消息
9.从机向客户端反馈成功消息

5.3 时序性

ZooKeeper 在处理分布式系统的数据一致性问题中的核心特性之一就是它的时序一致性,它由四种类型的时序构成:zxid, cversion, pzxid, mzxid,这些时序保证了ZooKeeper数据各种操作的一致性。

ZooKeeper 的时序一致性基于以下原则:

  1. 任何客户端将在其会话中看到一致且有序的修改。

  2. 具有相同ZooKeeper ID(也称为zxid)的更新在所有客户端中的顺序一致。

  3. 一旦更新被异步复制到备份ZooKeeper服务器并确认给客户端,那么所有看到此更新的后继客户端将看到该更新。

六.集群的选举过程

  1. 启动阶段:所有 ZooKeeper 服务器启动时,将自己的状态设置为 LOOKING。
  2. 投票阶段:每个服务器将投票给一个服务器(可能是它自己)。在这个阶段,每个服务器都创建一个新的事务日志,包含以下两个关键的信息:自己的服务器ID和最后处理的事务ID。这个投票将被发送给其他所有的 ZooKeeper 服务器。

(myid && Zxid )

  1. 投票比较阶段:每个服务器收到投票后,将进行比较。这个比较基于两个信息:最大的已处理事务ID和服务器ID。如果收到的投票的最大事务ID大于自身的最大事务ID,那么该服务器将更新自己的状态信息并将收到的投票的值作为自己的投票值,然后继续向其他服务器发送自己的投票信息。
  2. 决策阶段:当一个服务器从半数以上的服务器那里接收到相同的投票结果,就会更新自己的状态。如果这个服务器收到投票是它自己,那么它会成为领导者并改变自身状态为 LEADING。其他服务器将自己的状态改为 FOLLOWING。
  3. 领导者工作阶段:领导者开始处理写操作并将数据的更改广播给其他的服务器。这个过程保证了所有的服务器都能够同步保持一致的状态。

上述总结

每个zk 都有myid 和 Zxid

选举就是 根据最大的Zxid 和 myid 进行选举

补充 : zk与springboot整合参考

https://blog.csdn.net/weixin_43888891/article/details/125442668

https://blog.csdn.net/lushixuan12345/article/details/128201573

下方的是zookeeper分布式锁的实现

https://blog.csdn.net/Alian_1223/article/details/120852979

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值