Zookeeper是什么,为什么要用,怎么用?

打印 上一主题 下一主题

主题 525|帖子 525|积分 1575

关于Zookeeper的全面相识与应用

前言:这几天在开发过程中,碰到了zk相关的一些问题,大要先复习下
Zookeeper作为分布式系统中的协调服务,起着至关告急的脚色。本篇文章将从以下几个方面具体讲授什么是Zookeeper,为什么要使用Zookeeper,如何使用Zookeeper,以及它的工作原理。通过本篇文章,大家将全面相识并掌握Zookeeper的使用。
  

  • 1. 什么是Zookeeper
  • 2. 为什么使用Zookeeper
  • 3. Zookeeper的基本概念
  • 4. 如何使用Zookeeper

    • 4.1 安装Zookeeper
    • 4.2 启动Zookeeper服务器
    • 4.3 使用Zookeeper客户端

  • 5. Zookeeper的工作原理

    • 5.1 Zookeeper的数据结构
    • 5.2 选举过程
    • 5.3 写操作的处理
    • 5.4 读操作的处理

  • 6. 实际案例:实现分布式锁
  • 7. 总结
  1. 什么是Zookeeper

Zookeeper是一个开源的分布式协调服务,它提供了一种简单的、高性能的、高可用的协调机制。Zookeeper可以用来做配置管理、命名服务、分布式锁和集群管理等。它最初由雅虎开发,现在是Apache Software Foundation的顶级项目之一。
2. 为什么使用Zookeeper

在一个分布式系统中,多个节点之间需要进行协调和同步。常见的需求包罗:

  • 配置管理:集中管理和发布配置文件,确保多个节点同等性。
  • 命名服务:提供分布式系统中的命名剖析服务,如服务发现。
  • 分布式锁:实现分布式环境下的互斥锁机制,确保资源的串行访问。
  • 集群管理:管理和监控集群中的节点状态,进行故障检测和恢复。
Zookeeper基于其设计的强同等性和高可用性特点,高效地满意了分布式系统中的这些需求,增强了系统的稳固性和可靠性。
3. Zookeeper的基本概念

在深入相识Zookeeper的使用之前,我们需要相识一些基本概念:


  • 节点(ZNode):Zookeeper的数据结构是树状的,每个节点称为ZNode,每个ZNode都可以存储数据和子节点。
  • 会话(Session):客户端与Zookeeper服务器之间的毗连,每次毗连会生成一个唯一的Session ID。
  • 访问控制(ACL):控制对ZNode的访问权限,支持多种权限模式如读、写、创建、删除等。
  • 事件关照(Watchers):Zookeeper支持监听器机制,客户端可以注册监听器,当特定事件发生时,Zookeeper会关照客户端。
4. 如何使用Zookeeper

4.1 安装Zookeeper

从 Apache Zookeeper官网 下载Zookeeper安装包。解压后,配置 conf/zoo.cfg 文件如下:
  1. tickTime=2000
  2. dataDir=/var/zookeeper
  3. clientPort=2181
  4. initLimit=10
  5. syncLimit=5
  6. server.1=localhost:2888:3888
  7. server.2=localhost:2889:3889
  8. server.3=localhost:2890:3890
复制代码
4.2 启动Zookeeper服务器

在解压目次下,使用以下命令启动Zookeeper服务器:
  1. bin/zkServer.sh start
复制代码
4.3 使用Zookeeper客户端

可以通过以下命令启动Zookeeper客户端:
  1. bin/zkCli.sh -server localhost:2181
复制代码
然后,你可以在客户端执行创建、读取、更新和删除(CRUD)ZNode的命令,如下所示:
  1. # 创建节点
  2. create /myapp "Hello Zookeeper"
  3. # 读取节点数据
  4. get /myapp
  5. # 更新节点数据
  6. set /myapp "New Data"
  7. # 删除节点
  8. delete /myapp
复制代码
5. Zookeeper的工作原理

Zookeeper在分布式系统中的工作原理涉及多个方面:
5.1 Zookeeper的数据结构

Zookeeper的数据以树状目次结构存储,每个节点称为ZNode。ZNode可以保存数据和子节点。主要有两种类型的ZNode:


  • 持久节点(Persistent ZNode): 节点的生命周期与客户端会话无关,纵然客户端断开毗连,节点依然存在。
  • 临时节点(Ephemeral ZNode): 节点的生命周期依赖于客户端会话,当客户端断开毗连后,节点会自动删除。
5.2 选举过程

Zookeeper使用Zab协议(Zookeeper Atomic Broadcast)来实现分布式同等性。Zab协议包含两种模式:消息广播和领导者选举。在领导者选举过程中,全部节点会进行投票,选出一个唯一的领导者(Leader)。选举过程如下:

  • 全部服务器启动后进入选举状态。
  • 每个服务器投票给自己,并发送给其他服务器。
  • 收到投票后进行比对,更新投票并再次发送。
  • 重复投票过程,直到大多数服务器告竣同等,选出领导者。
5.3 写操作的处理

客户端发送写操作请求到Zookeeper,由Leader处理。Leader为请求分配事件ID(zxid),并将发起发给全部Follower。Follower收到发起并持久化后,发送确认信息给Leader。Leader收到半数以上Follower的确认后,提交事件,并关照全部Follower进行确认。
5.4 读操作的处理

读请求可以由任何服务器处理。客户端毗连到某个Zookeeper服务器,发起读请求。该服务器直接读取内容并返回给客户端。
6. 实际案例:实现分布式锁

在分布式系统中,分布式锁是一种常见需求。我们可以通过Zookeeper来实现分布式锁机制:
概述

通过创建临时次序节点来实现分布式锁的竞争,节点序列最小的获得锁,其余的监听比自己小的节点,释放锁时将节点删除,关照下一个节点进行竞争。
代码示例

  1. import org.apache.zookeeper.*;
  2. public class DistributedLock {
  3.     private static final String LOCK_ROOT = "/locks";
  4.     private ZooKeeper zk;
  5.     private String lockNode;
  6.     public DistributedLock(ZooKeeper zk) {
  7.         this.zk = zk;
  8.         try {
  9.             if (zk.exists(LOCK_ROOT, false) == null) {
  10.                 zk.create(LOCK_ROOT, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
  11.             }
  12.         } catch (Exception e) {
  13.             e.printStackTrace();
  14.         }
  15.     }
  16.     public void lock() {
  17.         try {
  18.             lockNode = zk.create(LOCK_ROOT + "/lock_", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
  19.             // Watch for the node preceding the created node
  20.             while (true) {
  21.                 List<String> children = zk.getChildren(LOCK_ROOT, false);
  22.                 Collections.sort(children);
  23.                 if (lockNode.endsWith(children.get(0))) {
  24.                     break;
  25.                 }
  26.                 // Wait for the previous node to be deleted
  27.                 int index = Collections.binarySearch(children, lockNode.substring(LOCK_ROOT.length() + 1));
  28.                 String previousNode = children.get(index - 1);
  29.                 final String previousNodePath = LOCK_ROOT + "/" + previousNode;
  30.                 final CountDownLatch latch = new CountDownLatch(1);
  31.                 zk.getData(previousNodePath, event -> {
  32.                     if (event.getType() == Watcher.Event.EventType.NodeDeleted) {
  33.                         latch.countDown();
  34.                     }
  35.                 }, null);
  36.                 latch.await();
  37.             }
  38.         } catch (Exception e) {
  39.             e.printStackTrace();
  40.         }
  41.     }
  42.     public void unlock() {
  43.         try {
  44.             if (lockNode != null) {
  45.                 zk.delete(lockNode, -1);
  46.                 lockNode = null;
  47.             }
  48.         } catch (Exception e) {
  49.             e.printStackTrace();
  50.         }
  51.     }
  52. }
复制代码
使用示例

  1. public class DistributedLockTest {
  2.     public static void main(String[] args) throws Exception {
  3.         ZooKeeper zk = new ZooKeeper("localhost:2181", 3000, null);
  4.         DistributedLock lock = new DistributedLock(zk);
  5.         lock.lock();
  6.         System.out.println("Acquired lock!");
  7.         // Perform some critical section operations
  8.         Thread.sleep(2000);
  9.         lock.unlock();
  10.         System.out.println("Released lock!");
  11.         zk.close();
  12.     }
  13. }
复制代码
7. 总结

Zookeeper作为分布式协调服务,广泛应用于各种分布式系统中。本篇文章具体介绍了Zookeeper的基本概念、使用方法和工作原理,并通过一个实际例子展示了如何实现分布式锁。盼望这篇文章能够帮助大家更好地明确和应用Zookeeper。
如有任何问题或建议,接待在评论区讨论交换!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

玛卡巴卡的卡巴卡玛

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表