zookeeper 的特性及其利用场景(分布式锁 和 Master选举)

zookeeper 的特性及其利用场景(分布式锁 和 Master选举)

zookeeper 的数据结构

Zookeeper 的数据模型和分布式文件系统类似,是一种层次化的属性结构,如图所示。和文件系统不同的是,Zookeeper的数据是结构化储存的,并没有在物理上体现出文件和目录。
在这里插入图片描述

​ Zookeeper 树中的每个节点被称为Znode,Znode维护了一个 Stat状态信息,其中包含数据变化的时间和版本等。并且每个Znode可以设置一个value值,Zookeeper并不用与通信的数据库或者大容量的对象储存,他只是管理和协调有关的数据,所以value的数据大小不建议设置的非常大,较大的数据会带来更大的网络开销。

​ Zookeeper 上的每个节点的数据都是允许读和写的,读表示获得指定Znode上的value数据,写表示修改指定Znode上的value数据。另外,节点的 创建规则和文件系统中文件的创建规则类似。必须按照层级创建。举个简单的例子,如果需要创建/node/node1/node1-1,那么必须先创建/node/node1这两个层级节点。

Zookeeper 的特性

Zookeeper 中 Znode在被创建的时候,需要指定节点的类型,节点类型分为:

  • 持久化节点,节点的数据会被持久化到磁盘、
  • 临时节点,节点的生命周期和创建改节点的客户端的声明周期一致,一旦该客户端的会话结束,则改客户端所创建的临时节点也会被删除。
  • 有序节点,在创建的节点后面会增加一个递增的序列,该序列在同一级父节点之下是唯一的。需要注意的是,持久化节点或者临时节点也是可以设置为有序节点的。也就是持久化节点或者临时有序节点。

在3.5.3 版本之后又增加了两种类型的节点,分别是

  • 容器节点,当容器节点下的最后一个节点被删除时,容器节点就会被删除。
  • TTL节点,针对持久化节点或者持久化有序节点,我们可以设置一个存活时间,如果在存活时间之内该节点没有任何修改并且没有任何子节点,它就会被自动删除。

需要注意的是,在同一层级目录下,节点的名称必须是唯一的,就像我们在同一个目录下不能创建两个相同名字的文件夹一样。

Watcher 机制

Zookeeper 提供了一种针对Znode的订阅/通知机制,也就是当Znode 节点状态发生变化或者Zookeeper 客户端连接状态发生变化时,会触发事件通知。这个机制在服务注册与发现中,针对服务调用者及时感知到服务提供者的变化提供了非常好的解决方案。

在 Zookeeper 提供的 java API 中, 提供了三种机制来针对Znode进行注册监听,分别是:

  • getData(),用于获取指定节点的value信息,并且可以注册监听,当监听的节点进行创建、修改、删除操作时,会触发·响应的事件通知。
  • getChildren(),用于获取指定及诶单的所有子节点,并且允许注册监听,当监听节点的子节点进行创建、修改、删除操作时,触发响应的事件通知。
  • exists(), 用于判断指定节点是否存在,同样可以注册对指定节点的监听,监听的时间类型和getData() 相同。

Watcher 事件的触发都是一次性的,比如客户端通过getData(‘/node’,true)注册监听,如果/node节点发生数据修改,那么该客户端会收到一个修改事件通知,但是/node再次发生变化时,客户端无法收到Watcher事件,为了解决这个问题,客户端必须在收到的事件回调中再测注册事件。

常见应用场景分析

基于Zookeeper 中节点的特性,可以为多种应用场景提供解决方案。

分布式锁

我们可以使用zookeeper的特性来实现分布式锁,锁的本质是排他性,就是避免在同一时刻多个进程访问某一个共享资源。

利用临时节点的特性,及同时节点的唯一性就可以完成这一个操作。

  • 获取锁的过程

    在获取排他锁时,所有客户端可以去Zookeeper 服务器上 /Exclusive_Locks 节点下创建一个临时节点 /lock。Zookeeper 基于同级节点的唯一性,会保证所有客户端中只有一个客户端能创建成功,创建成功的客户端获得了排他锁,没有获得锁的客户端就需要通过Watcher机制监听/Exclusive_Locks 节点下子节点的变更事件。

  • 释放锁的过程

    在获得锁的过程,我们定义的锁节点/lock 为临时节点,根据临时节点的特性,在下面两种情况下会触发锁的释放。

    • 获得锁的客户端因为异常断开了和服务器的连接,基于临时节点,/lock 节点会被自动删除。
    • 获得锁的客户端执行完业务逻辑之后,主动删除了创建的/lock 节点。

    当/ lock 节点被删除后,Zookeeper 会通知其他监听了/Exclusive_Locks 子节点变化的客户端。这些客户端收到通知后,再次发起创建/lock 节点的操作来获得排他锁。

Master 选举

Master 选举是分布式系统中非常常见的场景,在分布式架构中,为了保证服务的可用性,通常会采用集群模式,也就是当其中一个机器宕机后,集群中的其他节点会接替故障节点继续工作。在这种场景下,就需要 从集群中选举一个节点作为Master节点,剩余的节点都作为备份节点随时待命。当原有的Master节点出现故障后,还需要从集群中的其他备份节点中选举一个节点作为Master节点继续提供服务。

  • 同一节点不能重复创建一个已经存在的节点,这个有点类似于分布式锁的实现场景,其实Master选举的场景也是如此。假设集群中有3个节点,需要选举出Master,那么这三个节点同时去Zookeeper服务器上创建一个临时节点 /master-election,由于节点的特性,只有一个客户端会创建成功,针对该节点注册Watcher事件,用于监控当前的Master机器是否存活,一旦发现Master “挂了”,也就是/master-election节点被删除了,那么其他的客户端将会重新发起Master选举操作。

  • 利用临时有序节点的特性实现。所有参与选举的客户端在Zookeepeer 服务器的/master节点下创建一个临时有序节点,编号最小的节点表示Master,后续的节点可以监听前一个节点的删除时间,用于触发重新选举。

例子:client01、client02、client03三个节点去Zookeeper Server 的/master 节点下创建临时有序节点,编号最小的节点client01表示Master节点,client02 和 client03 三个节点去 Zookeeper Server 的/master 节点下创建临时有效节点,client01 创建 /client01-0000000001 ,client-02 创建 /client02-0000000003,client-03 创建 /client03-0000000002, 编号最小的节点 client01 表示Master节点,client02 和 clinet03 分别会通过 Watcher 机制监听比自己编号小的一个节点。如client02 监听/client03-0000000002,client03 监听/client01-0000000001, 如果最小的节点被删除了,那么client03便会被选举为Master。

image-20220508214723763

Zookeeper 注册中心的实现原理

Dubbo 服务注册到Zookeeper 上之后,可以在Zookeeper服务器上看到如下图所示的树形结构。

image-20220508220735081

​ 当Dubbo服务启动时,会取Zookeeper服务器上的 /dubbbo/com.scmpe.dubbo.IHelloService/provides目录下创建当前服务的URL,其中com.scmpe.dubbo.IHelloService是发布服务的接口全路径名称,providers表示服务提供者的类型,dubbo://ip:port 表示服务发布的协议类型及访问地址。其中,URL是临时节点,其他皆为持久化节点。在这里URL为什么使用临时节点呢,因为如果注册该节点的服务器下线了,那么这个服务器·的URL地址就会从Zookeeper服务器上被移除。

​ 当Dubbo 服务消费者启动时,会对/dubbbo/com.scmpe.dubbo.IHelloService/provides节点下的子节点注册Watcher监听,这样便可以感知到服务提供方节点的上下线变化,而防止请求发送到已经下线的服务器造成访问失败。同时,服务消费者会在/dubbbo/com.scmpe.dubbo.IHelloService/cosumers 下写入自己的URL,这样做的目的是可以在监控平台上看到某个Dubbo服务正在被哪些服务调用;最重要的是,Dubbo服务的消费者如果需要调用IHelloService服务,那么它先回去/dubbbo/com.scmpe.dubbo.IHelloService/provides 路径下获得所有服务的提供方URL列表,然后通过负载均衡算法计算出一个地址进行远程访问。

​ 整体来看,服务注册和动态感知的功能用到了Zookeeper 中的临时节点,持久化节点、Watcher等,回头看前面分析的Zookeeper的应用场景可以发现,几乎所有的场景都是基于这些来完成的。另外,不得不提的是,Dubbo还可以针对不同的情况实现以下功能。

  • 基于临时节点的特性,当服务提供者宕机或者下线时,注册中心会自动删除该服务提供者的信息
  • 注册中心重启时,Dubbo能够自动回复注册数据及订阅请求。
  • 为了保证节点操作的安全性,Zookeeper提供了ACL权限控制,在Dubbo中可以通过 dubbo.registry.username/dubbo.registry.password 设置节点的验证信息。
  • 注册中心默认的根节点是/dubbo,如果需要针对不同环境设置不同的根节点,可以使用dubbo.registry.group修改根节点名称。

猜你喜欢

转载自blog.csdn.net/qq_45473439/article/details/124661624