ZooKeeper知识点总结及分布式锁实现

发布于:2024-05-05 ⋅ 阅读:(24) ⋅ 点赞:(0)

    最初接触ZooKeeper是之前的一个公司的微服务项目中,涉及到Dubbo和ZooKeeper,ZooKeeper作为微服务的注册和配置中心。好了,开始介绍ZooKeeper了。

目录

1.ZooKeeper的基本概念

2.ZooKeeper的节点(ZNode)

3. ZooKeeper的Watcher机制

4. ZooKeeper的会话(Session)

5. ZooKeeper的领导者选举

6. ZooKeeper的持久性和临时性节点

7. ZooKeeper的ACL(访问控制列表)

 8.ZooKeeper的集群模式

9. ZooKeeper的典型应用场景

 10.ZooKeeper的会话超时和重连机制

11. ZooKeeper的故障恢复机制

 12.ZooKeeper的事务处理

13. ZooKeeper的Watcher事件和状态

14. ZooKeeper的四字节数字表示

 15.ZooKeeper的Chroot特性

16.ZooKeeper的JMX(Java Management Extensions)管理 

17. ZooKeeper的Quorum Peer通信

18. ZooKeeper的Follower和Observer角色

19. ZooKeeper Administrator(ZK Admin)命令行工具

20.ZooKeeper的ZooInspector可视化工具

​ 21.Spring Boot整合ZooKeeper实现分布式锁


1.ZooKeeper的基本概念
知识点 描述 示例
什么是ZooKeeper 分布式协调服务 ZooKeeper是一个开源的分布式协调服务,用于维护配置信息、命名、提供分布式同步和提供组服务等。
设计目标 简单、健壮、易于编程 ZooKeeper的设计目标是简单、健壮、易于编程,它能够保证在分布式环境中的一致性。
核心特性 一致性、可靠性、有序性 ZooKeeper的核心特性包括一致性、可靠性和有序性,确保分布式环境中的数据一致性。
数据模型 树形结构 ZooKeeper的数据模型是类似于文件系统的树形结构,称为ZNode。每个ZNode可以存储数据和子节点。
应用场景 分布式锁、配置管理等 ZooKeeper常用于实现分布式锁、配置管理、负载均衡、命名服务等。
2.ZooKeeper的节点(ZNode)
知识点 描述 示例
ZNode类型 持久节点和临时节点 持久节点会一直存在,直到被显式删除;临时节点在创建它的会话结束时自动删除。
ZNode数据 存储数据 每个ZNode可以存储一定量的数据,通常用于存储配置信息或状态信息。
顺序性 顺序ZNode 可以创建顺序ZNode,ZooKeeper会在创建时在ZNode名称后添加一个数字,表示创建顺序。
监听器 监听节点变化 可以为ZNode设置监听器,当ZNode的数据或子节点发生变化时,监听器会被触发。
权限控制 ACL(Access Control Lists) ZooKeeper支持权限控制,可以为不同的ZNode设置不同的访问权限。
3. ZooKeeper的Watcher机制
知识点 描述 示例
Watcher定义 事件监听器 Watcher是ZooKeeper中的事件监听器,用于监听ZNode上的变化。
触发事件 数据变更、状态变更 Watcher可以监听数据节点的内容变化、子节点的添加或删除,以及客户端与服务器之间的状态变化。
一次性触发 单次触发 Watcher是一次性的,一旦触发,就会移除,如果需要持续监听,需要重新注册。
事件类型 多种事件类型 包括节点创建、删除、更改以及客户端连接状态变化等。
应用场景 状态同步、触发动作 常用于实现分布式协调、状态同步,以及在节点变化时触发某些动作。
4. ZooKeeper的会话(Session)
知识点 描述 示例
会话概念 客户端与ZooKeeper的连接 会话是客户端与ZooKeeper之间的一个TCP连接,用于客户端与ZooKeeper之间的通信。
会话ID 唯一标识 每个会话都有一个唯一的会话ID,用于识别特定的会话。
超时机制 保持会话活跃 如果会话在一定时间内没有收到心跳,ZooKeeper将认为会话超时,并释放该会话创建的所有临时节点。
心跳 维持连接 客户端周期性地向ZooKeeper发送心跳以保持会话活跃。
状态 连接状态 会话状态包括连接成功、连接超时、会话关闭等。
5. ZooKeeper的领导者选举
知识点 描述 示例
领导者选举 集群中的主节点 在ZooKeeper集群中,领导者(Leader)负责处理所有事务请求,并与跟随者(Follower)和观察者(Observer)进行通信。
选举过程 自动进行 当集群中的领导者崩溃或失去连接时,集群会自动进行领导者选举。
投票机制 基于ZXID 领导者选举过程中,节点通过投票来决定新的领导者,投票通常基于ZXID(事务ID)来确保一致性。
法定人数 多数投票 选举新的领导者需要集群中多数节点的投票。
容错能力 高可用性 领导者选举机制确保了ZooKeeper集群的高可用性,即使部分节点失效,集群也能继续工作。
6. ZooKeeper的持久性和临时性节点
知识点 描述 示例
持久性节点 长期存储 创建后,除非被客户端显式删除,否则持久性节点会一直存在于ZooKeeper中。
临时性节点 会话关联 临时性节点与创建它的会话生命周期绑定,会话结束时,临时节点被自动删除。
顺序节点 自增序号 可以创建带有顺序的持久性或临时性节点,ZooKeeper会在节点名后添加一个自增的序列号。
持久性顺序节点 持久且有序 结合了持久性和顺序性的特点,适用于需要持久化存储且需要顺序标识的场景。
应用场景 任务调度、分布式锁 持久性节点常用于存储长时间不变的信息,而临时性节点常用于实现轻量级的分布式锁或任务调度。
7. ZooKeeper的ACL(访问控制列表)
知识点 描述 示例
ACL定义 访问控制机制 ACL是ZooKeeper提供的访问控制机制,用于控制对ZNode的访问权限。
权限类型 认证与授权 包括对ZNode的读、写、创建、删除等操作的权限。
认证方案 基于角色的访问控制 可以为不同的角色或用户设置不同的权限,实现细粒度的访问控制。
权限设置 与ZNode关联 权限是与特定的ZNode关联的,可以为每个ZNode设置不同的ACL。
安全性 增强系统安全性 通过ACL可以增强ZooKeeper集群的安全性,防止未授权访问。
 8.ZooKeeper的集群模式
知识点 描述 示例
集群组成 多个ZooKeeper服务器 一个ZooKeeper集群由多个ZooKeeper服务器组成,提供高可用性和可扩展性。
领导者(Leader) 事务处理 Leader服务器负责处理所有事务请求,是集群中的主要工作节点。
跟随者(Follower) 数据复制 Follower服务器从Leader复制数据,处理非事务请求,参与领导者选举。
观察者(Observer) 读请求处理 Observer服务器不参与投票,只用于处理客户端的读请求,提高集群的读取性能。
容错机制 自动故障转移 当Leader服务器出现故障时,集群会自动进行领导者选举,实现故障转移。
9. ZooKeeper的典型应用场景
知识点 描述 示例
分布式锁 协调分布式系统中的进程 使用ZooKeeper的临时性节点和监听器实现分布式锁,确保资源在分布式环境中的互斥访问。
配置管理 集中管理配置信息 将系统配置存储在ZooKeeper的ZNode中,便于分布式系统中的各个节点获取和监听配置变化。
集群管理 管理集群节点状态 利用ZooKeeper来监控和管理集群中的节点状态,如节点的加入、退出和故障检测。
队列管理 分布式队列 使用ZooKeeper的顺序节点和监听器实现分布式队列,用于任务调度和负载均衡。
发布/订阅 事件通知 客户端可以订阅ZooKeeper上的主题,当主题发生变化时,ZooKeeper可以通知所有订阅的客户端。
 10.ZooKeeper的会话超时和重连机制
序号 知识点 描述 示例
1 会话超时 客户端连接丢失 当客户端与ZooKeeper服务器的连接中断,如果在超时时间内未能重新连接,则会话将被认为超时。
2 超时时间 可配置 会话超时时间是可以配置的,通常根据应用需求和网络状况来设置。
3 临时节点 自动删除 如果会话超时,客户端创建的所有临时节点将被ZooKeeper自动删除。
4 重连机制 客户端尝试重新连接 客户端在检测到连接丢失后,会尝试重连到ZooKeeper集群中的其他服务器。
5 监听器 重新注册 在重连成功后,客户端需要重新注册之前设置的监听器,以继续监控ZNode的变化。
11. ZooKeeper的故障恢复机制
知识点 描述 示例
故障检测 心跳机制 ZooKeeper使用心跳机制来检测服务器和客户端的连接状态,如果心跳超时则认为连接断开。
领导者选举 自动进行 当领导者出现故障时,集群会自动触发领导者选举过程以选出新的领导者。
数据同步 确保一致性 跟随者和观察者节点会与领导者节点进行数据同步,以保证数据的一致性。
持久化存储 保证数据不丢失 ZooKeeper的事务日志和快照用于数据的持久化存储,确保在故障恢复后数据不会丢失。
快速恢复 减少停机时间 通过优化故障恢复流程,ZooKeeper可以快速从故障中恢复,减少系统的停机时间。
 12.ZooKeeper的事务处理
知识点 描述 示例
事务定义 操作序列 事务是一组不可分割的ZooKeeper操作序列,要么全部成功,要么全部失败。
事务ID ZXID 每个事务都有一个唯一的事务ID(ZXID),用于标识事务操作。
写操作 更新ZNode 写操作包括创建节点、删除节点、设置节点数据等。
原子性 事务操作的原子性 事务保证了操作的原子性,要么所有操作都被执行,要么都不执行。
事务日志 持久化事务信息 事务信息会被记录在事务日志中,确保事务的持久性和可靠性。
13. ZooKeeper的Watcher事件和状态
知识点 描述 示例
事件类型 多种事件 Watcher可以监听包括节点变更、子节点列表变更、连接状态变更等多种事件。
事件触发 异步通知 当Watcher监听的事件被触发时,ZooKeeper会异步地通知客户端。
状态变化 连接状态 Watcher可以监听客户端与ZooKeeper服务器之间的连接状态,如连接丢失或重新连接。
一次性 触发后移除 Watcher在触发一次后会被自动移除,需要重新设置以继续监听。
应用 实时响应 通过Watcher机制,客户端可以实时响应ZooKeeper中的变化,如节点数据更新或子节点添加。
14. ZooKeeper的四字节数字表示
知识点 描述 示例
四字节数字 计数方式 ZooKeeper使用四字节数字来表示节点版本号、事务ID等,范围从1到2^31-1。
计数器 递增 每个事务后,相关的计数器(如ZXID的计数器)递增,确保每个事务ID唯一。
持久性 持久化 四字节数字的持久化确保了在ZooKeeper重启后,计数器不会丢失。
版本号 节点版本控制 每个ZNode都有版本号,包括节点版本和子节点版本,用于冲突解决和缓存一致性。
应用 事务一致性 四字节数字在ZooKeeper的内部事务处理中起到关键作用,确保事务的顺序和一致性。
 15.ZooKeeper的Chroot特性
知识点 描述 示例
Chroot特性 命名空间隔离 Chroot允许在ZooKeeper实例中创建一个命名空间,用于隔离不同用户或应用的数据。
使用场景 多租户支持 通过Chroot,可以在单个ZooKeeper实例上运行多个虚拟ZooKeeper服务。
语法 路径指定 使用Chroot时,通过在ZooKeeper的连接字符串后面添加一个斜杠和特定路径来指定命名空间。
限制 性能影响 Chroot特性可能会对ZooKeeper的性能产生一定影响,尤其是在大量的watcher和频繁的节点操作时。
应用 数据隔离 适用于需要严格数据隔离和安全性要求的场景,如不同团队或项目之间的数据隔离。
16.ZooKeeper的JMX(Java Management Extensions)管理 
知识点 描述 示例
JMX定义 管理接口 JMX是Java平台内建的一套管理接口,用于监控和管理Java应用程序。
MBeans 管理豆 MBeans是JMX的组件,代表可以被监控和管理的资源,如内存使用、线程状态等。
连接 使用JMX连接 ZooKeeper提供了JMX连接,允许管理员远程监控和操作ZooKeeper实例。
监控 实时数据 通过JMX可以实时监控ZooKeeper的运行状态,包括客户端连接数、请求数、数据节点状态等。
管理 动态调整 JMX允许管理员在运行时动态地调整ZooKeeper的配置,如更改日志级别、重启服务等。
17. ZooKeeper的Quorum Peer通信
知识点 描述 示例
Quorum Peer 集群节点 在ZooKeeper中,每个服务器节点被称为一个Quorum Peer,它们组成一个领导者和多个跟随者的集群。
通信机制 TCP/IP协议 Quorum Peers之间的通信基于TCP/IP协议,用于数据同步和领导者选举。
领导者选举 集群协调 当集群中的领导者崩溃时,Quorum Peers会进行领导者选举以选出新的领导者。
消息传递 心跳和提案 Quorum Peers通过发送心跳消息来维持连接,并使用提案消息来提交事务。
持久化 事务日志 每个Quorum Peer都会持久化事务日志,确保在故障恢复后数据的一致性。
18. ZooKeeper的Follower和Observer角色
知识点 描述 示例
Follower角色 数据复制 Follower节点接收来自Leader的更新,并将这些更新应用到本地数据库。
Observer角色 读请求 Observer节点不参与投票,主要处理客户端的读取请求,提高读取吞吐量。
角色转换 动态变化 在ZooKeeper集群中,Follower可以在需要时被配置为Observer,反之亦然。
数据同步 保持一致 Follower和Observer都会从Leader同步数据,以保证集群中数据的一致性。
应用场景 高可用与扩展性 Observer用于提高集群的读取性能,而不增加投票过程的开销,适用于读多写少的场景。
19. ZooKeeper Administrator(ZK Admin)命令行工具
知识点 描述 示例
ZK Admin 命令行工具 ZK Admin是ZooKeeper提供的命令行工具,用于管理ZooKeeper集群。
功能 集群管理 可以执行如查看集群状态、查看服务器统计信息、触发领导者选举等操作。
使用 命令行界面 通过命令行界面,输入特定的命令来执行管理任务。
参数 命令选项 提供多种参数和选项,允许管理员根据需要定制操作。
应用场景 集群运维 常用于ZooKeeper的日常运维,如配置更改、状态监控和故障排查。
20.ZooKeeper的ZooInspector可视化工具
知识点 描述 示例
ZooInspector 可视化工具 ZooInspector是一个用于可视化ZooKeeper数据树的Java应用程序。
功能 数据浏览 允许用户浏览和管理ZooKeeper服务中的ZNode数据。
用户界面 图形界面 提供图形用户界面,使得操作ZooKeeper的数据更加直观和方便。
特点 实时更新 可以实时显示ZooKeeper中的更改,包括节点的创建、删除和数据变更。
应用场景 数据管理和调试 适用于开发和测试阶段,帮助开发者更好地理解和管理ZooKeeper中的数据结构。

Windows系统可以使用zktool工具,需要jdk1.8以上。

 
21.Spring Boot整合ZooKeeper实现分布式锁

在Spring Boot中整合ZooKeeper实现分布式锁,通常需要以下步骤:

  1. 添加ZooKeeper依赖:在项目的pom.xml文件中添加ZooKeeper客户端库的依赖。

  2. 配置ZooKeeper连接:在application.propertiesapplication.yml中配置ZooKeeper的连接字符串。

  3. 创建分布式锁的接口:定义一个分布式锁的接口,包含加锁和释放锁的方法。

  4. 实现分布式锁:使用ZooKeeper的客户端库实现分布式锁的逻辑。

  5. 使用分布式锁:在需要同步的代码块中使用分布式锁。

下面是一个简单的代码示例:

pom.xml 添加ZooKeeper依赖:

<dependencies>
    <!-- ZooKeeper客户端 -->
    <dependency>
        <groupId>org.apache.zookeeper</groupId>
        <artifactId>zookeeper</artifactId>
        <version>3.7.0</version>
    </dependency>
    <!-- Spring Boot Starter -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
        <version>2.7.0</version>
    </dependency>
</dependencies>

application.yml 配置ZooKeeper连接:

spring:
  zookeeper:
    host: localhost:2181 # ZooKeeper服务器地址

 分布式锁接口和实现

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.concurrent.CountDownLatch;

@Component
public class DistributedLock {
    
    @Value("${spring.zookeeper.host}")
    private String zkHost;

    private ZooKeeper zkClient;
    
    private static final String LOCK_PATH = "/distributed_lock";

    public void init() throws Exception {
        // 连接ZooKeeper
        CountDownLatch countDownLatch = new CountDownLatch(1);
        zkClient = new ZooKeeper(zkHost, 5000, (watchedEvent) -> {
            if (watchedEvent.getState() == Watcher.Event.KeeperState.SyncConnected) {
                countDownLatch.countDown();
            }
        });
        countDownLatch.await();
    }

    public boolean tryLock(String lockName) throws Exception {
        String lockNode = zkClient.create(
                LOCK_PATH + "/" + lockName,
                "".getBytes(),
                ZooDefs.Ids.OPEN_ACL_UNSAFE,
                CreateMode.EPHEMERAL_SEQUENTIAL
        );

        // 检查是否是最小序号的节点,即获取锁
        Stat stat = zkClient.exists(lockNode, false);
        if (stat != null) {
            long currentSequence = Long.parseLong(lockNode.substring(lockNode.lastIndexOf('-') + 1));
            while (true) {
                List<String> children = zkClient.getChildren(LOCK_PATH, false);
                long minSequence = Long.MAX_VALUE;
                for (String node : children) {
                    long sequence = Long.parseLong(node.substring(node.lastIndexOf('-') + 1));
                    if (sequence < minSequence) {
                        minSequence = sequence;
                    }
                }
                if (currentSequence == minSequence) {
                    // 成功获得锁
                    return true;
                }
                Thread.sleep(100);
            }
        } else {
            // 创建节点失败
            return false;
        }
    }

    public void unlock(String lockNode) throws Exception {
        zkClient.delete(lockNode, -1);
    }
}

使用分布式锁

@Service
public class SomeService {

    private final DistributedLock distributedLock;

    public SomeService(DistributedLock distributedLock) {
        this.distributedLock = distributedLock;
    }

    public void someMethod() {
        try {
            if (distributedLock.tryLock("myLock")) {
                // 执行业务逻辑
                distributedLock.unlock("/path/to/lock/node");
            } else {
                // 没有获得锁,进行其他逻辑处理
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

请注意,这个示例只是一个比较简略的版本,实际的项目中使用,可能需要考虑更多的异常处理和资源清理。另外,分布式锁的实现可能需要根据具体的业务场景和需求进行调整。

      昨晚把大学时期总结的英语形近词从我的百度文库个人主页下载下来优化整理了一下,那时候大概总结整理了几千个英语形近词,当时是为了应付一下考研英语科目。现在准备学习英语口语,单词仍然是基础,还需要再次复习复习。过几天会把这些整理到CSDN中,哈哈哈,马上要做英语博主了!


网站公告

今日签到

点亮在社区的每一天
去签到