hadoop之zookeeper

本文介绍了Zookeeper作为分布式服务框架的基础概念,包括其在解决分布式一致性问题中的角色、基本架构和核心组件。详细探讨了Znode的数据结构特性、Watcher机制以及Zookeeper提供的基本操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Zookeeper 作为一个分布式的服务框架,主要用来解决分布式集群中应用系统的一致性问题,它能提供基于类似于文件系统的目录节点树方式的数据存储, Zookeeper 作用主要是用来维护和监控存储的数据的状态变化,通过监控这些数据状态的变化,从而达到基于数据的集群管理。
1 Zookeeper基本框架
Zookeeper集群主要角色有Leader,Learner(Follower,Observer(当服务器增加到一定程度,由于投票的压力增大从而使得吞吐量降低,所以增加了Observer。)以及client:
Leader:领导者,负责投票的发起和决议,以及更新系统状态
Follower:接受客户端的请求并返回结果给客户端,并参与投票
Observer:接受客户端的请求,将写的请求转发给leader,不参与投票。Observer目的是扩展系统,提高读的速度。
Client:客户端,想Zookeeper发起请求。
Zookeeper的基本框架图如下:
这里写图片描述

1). Znode
Zookeeper数据结构中每个节点称为Znode,每个Znode都有唯一的路径,znode 可以有子节点目录,并且每个 znode 可以存储数据。znode是有版本的,每个 znode 中存储的数据可以有多个版本,也就是一个访问路径中可以存储多份数据。
Znode 基本类型 :
PERSISTENT:持久化znode节点,一旦创建这个znode点存储的数据不会主动消失,除非是客户端主动的delete。
PERSISTENT|SEQUENTIAL:顺序自动编号的znode节点,这种znoe节点会根据当前已近存在的znode节点编号自动加 1,而且不会随session断开而消失。
EPHEMERAL:临时znode节点,Client连接到zk service的时候会建立一个session,之后用这个zk连接实例创建该类型的znode,一旦Client关闭了zk的连接,服务器就会清除session,然后这个session建立的znode节点都会从命名空间消失。总结就是,这个类型的znode的生命周期是和Client建立的连接一样的。
PHEMERAL|SEQUENTIAL:临时自动编号节点,znode节点编号会自动增加,但是会随session消失而消失。
Zookeeper它只负责协调数据,一般 Znode上的数据都比较小以Kb为测量单位。Zookeeper的client和server的实现类都会验证znode存储的数据是否小于1M。如果数据比较大时,Server之间进行数据同步会消耗比较长的时间,影响系统性能。
2).Watcher
Zookeeper中znode产生某种行为(事件)时,如何让客户端得到通知,进行相关操作?Zookeeper中使用Watcher机制,可以针对ZooKeeper服务的“操作”来设置观察,该服务的其他操作可以触发观察。
Zookeeper中的watcher机制类型:
Exists:在path上执行NodeCreated ,NodeDeleted ,NodeDataChanged .
getData Watcher: 在path上执行 NodeDataChanged ,NodeDeleted .
getChildrenWatcher:在paht上执行NodeDeleted .或在子path上执行NodeCreated ,NodeDeleted 。
Zookeeper中对于某个节点设置Watcher是一次性的,在Znode上watcher触发后会删除该Watcher,所以如果需要对某个Znode节点进行长期关注,在事件触发后,需要在该Znode上重置Watcher。

3).基本操作
创建节点:
Stringcreate(String path,byte[] data, List acl,CreateMode createMode)
创建一个给定的目录节点 path, 并给它设置数据,CreateMode 标识有四种形式的目录节点
删除节点:
void delete(String path,int version)
删除 path 对应的目录节点,version 为 -1 可以匹配任何版本,也就删除了这个目录节点所有数据
查询节点是否存在:
Stat exists(String path,boolean watch/Watcher watcher)
判断某个 path 是否存在,并设置是否监控这个目录节点
获取节点数据:
byte[] getData(String path,boolean watch, Stat stat)
获取这个 path 对应的目录节点存储的数据,数据的版本等信息可以通过 stat 来指定,同时还可以设置是否监控这个目录节点数据的状态
设置节点数据:
Stat setData(String path,byte[] data, int version)
给 path 设置数据,可以指定这个数据的版本号,如果 version 为 -1 怎可以匹配任何版本
获取节点的子节点:
List getChildren(String path,boolean watch)
获取指定 path 下的所有子目录节点,同样 getChildren方法也有一个重载方法可以设置特定的 watcher 监控子节点的状态

import org.apache.zookeeper.CreateMode;  
import org.apache.zookeeper.WatchedEvent;  
import org.apache.zookeeper.Watcher;  
import org.apache.zookeeper.ZooDefs;  
import org.apache.zookeeper.ZooKeeper;  


public class ZkTest {  
    public static void main(String[] args) throws Exception {  
        // 创建一个与服务器的连接  
        ZooKeeper zk = new ZooKeeper("node3", 3000, new Watcher() {  
            // 监控所有被触发的事件  
            public void process(WatchedEvent event) {  
                System.out.println("已经触发了" + event.getType() + "事件" + event.getPath());  
            }  
        });  
        // 创建一个目录节点  
        zk.create("/testPath", "testData".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE,  
                CreateMode.PERSISTENT);  
        System.out.println(new String(zk.getData("/testPath", false, null)));  

        // 创建一个子目录节点  
        zk.create("/testPath/testChildPathOne", "testChildDataOne".getBytes(),  
                ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);  
        System.out.println(new String(zk.getData("/testPath/testChildPathOne", true, null)));  


        // 取出子目录节点列表  
        System.out.println(zk.getChildren("/testPath", true));  


        // 修改子目录节点数据  
        zk.setData("/testRootPath/testChildPathOne", "modifyChildDataOne".getBytes(), -1);  
        System.out.println(new String(zk.getData("/testPath/testChildPathOne", false, null)));  
        System.out.println("目录节点状态:[" + zk.exists("/testPath", true) + "]");  



        // 创建另外一个子目录节点  
        zk.create("/testPath/testChildPathTwo", "testChildDataTwo".getBytes(),  
                ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);  
        System.out.println(new String(zk.getData("/testPath/testChildPathTwo", false, null)));  

        // 删除子目录节点  
        zk.delete("/testPath/testChildPathTwo", -1);  
        zk.delete("/testPath/testChildPathOne", -1);  

        // 删除父目录节点  
        zk.delete("/testPath", -1);  
        // 关闭连接  
        zk.close();  
    }  
}  
1
2
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值