zookeeper(2) 文件系统
这一节我们主要来看一下zookeeper文件系统的实现。
树结构
为了提高对指定节点的操作,zookeeper使用一个HashMap来存储树结构数据,key为数据路径,value为节点数据。
树节点(DataNode)
public class DataNode implements Record {
//父节点
DataNode parent;
//节点数据
byte data[];
//节点权限
Long acl;
//节点状态信息
public StatPersisted stat;
//子节点名
private Set<String> children = null; }
数节点状态(StatPersisted)
public class StatPersisted implements Record {
//该节点创建是的事务xid
private long czxid;
//该节点最后一次修改的事务id
private long mzxid;
//创建时间
private long ctime;
//最后一次修改时间
private long mtime;
//节点版本号
private int version;
//子节点版本号
private int cversion;
//acl版本号
private int aversion;
//是否为零时节点
private long ephemeralOwner;
//子列表被修改的zxid
private long pzxid;
}
配额管理
zookeeper在创建、修改节点时可以设置特定路径上的配额。在实现上,配额也存储在文件系统中,并且还存储了节点当前的信息。配额的控制在特定的路径下:/zookeeper/quota/{节点路径}/zookeeper_limits 节点的限制数据节点;/zookeeper/quota/{节点路径}/zookeeper_stats 节点的当前量节点。一个节点路径中只能有一个配额限制。
当在对某个节点进行操作时,我们需要知道该路径下的哪个节点设置了配额,因为树结构使用hashmap来存储,所以不便于通过路径查找,所以使用了一个树结构来表示那个节点上配置了限额。
配额路径(PathTrie)
public class PathTrie {
//根节点
private final TrieNode rootNode ;
//节点
static class TrieNode {
//是否设置配额,false没有,true有
boolean property = false;
//子节点
final HashMap<String, TrieNode> children;
//父节点
TrieNode parent = null; //删除子节点配额
void deleteChild(String childName) {
synchronized(children) {
if (!children.containsKey(childName)) {
return;
}
TrieNode childNode = children.get(childName);
//如果子节点没有自己点直接删除,否则设置property为false
if (childNode.getChildren().length == 1) {
childNode.setParent(null);
children.remove(childName);
}
else {
childNode.setProperty(false);
}
}
}
}
//新增配额节点
public void addPath(String path) {
if (path == null) {
return;
}
String[] pathComponents = path.split("/");
TrieNode parent = rootNode;
String part = null;
if (pathComponents.length <= 1) {
throw new IllegalArgumentException("Invalid path " + path);
}
for (int i=1; i<pathComponents.length; i++) {
part = pathComponents[i];
if (parent.getChild(part) == null) {
parent.addChild(part, new TrieNode(parent));
}
parent = parent.getChild(part);
}
parent.setProperty(true);
} //删除配额节点
public void deletePath(String path) {
if (path == null) {
return;
}
String[] pathComponents = path.split("/");
TrieNode parent = rootNode;
String part = null;
if (pathComponents.length <= 1) {
throw new IllegalArgumentException("Invalid path " + path);
}
for (int i=1; i<pathComponents.length; i++) {
part = pathComponents[i];
if (parent.getChild(part) == null) {
return;
}
parent = parent.getChild(part);
}
TrieNode realParent = parent.getParent();
realParent.deleteChild(part);
} //获取指定路径上配额节点最大路径
public String findMaxPrefix(String path) {
if (path == null) {
return null;
}
if ("/".equals(path)) {
return path;
}
String[] pathComponents = path.split("/");
TrieNode parent = rootNode;
List<String> components = new ArrayList<String>();
if (pathComponents.length <= 1) {
throw new IllegalArgumentException("Invalid path " + path);
}
int i = 1;
String part = null;
StringBuilder sb = new StringBuilder();
//最大路径的index
int lastindex = -1;
while((i < pathComponents.length)) {
if (parent.getChild(pathComponents[i]) != null) {
part = pathComponents[i];
parent = parent.getChild(part);
components.add(part);
if (parent.getProperty()) {
lastindex = i-1;
}
}
else {
break;
}
i++;
}
for (int j=0; j< (lastindex+1); j++) {
sb.append("/" + components.get(j));
}
return sb.toString();
}
}
监听器管理
zookeeper可以对指定路径进行监听,当指定路径发生变化时,监听器会执行响应的动作。主要是通过将path和watcher建立关联关系,在对指定路径进行操作是调用相应监听器方法。
监听管理器(WatchManager)
public class WatchManager {
//key为path value为该path对应的watcher集合
private final HashMap<String, HashSet<Watcher>> watchTable =
new HashMap<String, HashSet<Watcher>>();
//key为watcher value为该watcher对应的path集合,使用两个hashmap来维护路径和监听器是因为watcher和路径是多对多关系,这样无论通过watcher还是路径都可以很快找到对应的路径和watcher。
private final HashMap<Watcher, HashSet<String>> watch2Paths =
new HashMap<Watcher, HashSet<String>>(); public synchronized void addWatch(String path, Watcher watcher) {
//新增watcher到watchTable
HashSet<Watcher> list = watchTable.get(path);
if (list == null) {
list = new HashSet<Watcher>(4);
watchTable.put(path, list);
}
list.add(watcher);
//新增watcher到watch2Paths
HashSet<String> paths = watch2Paths.get(watcher);
if (paths == null) {
paths = new HashSet<String>();
watch2Paths.put(watcher, paths);
}
paths.add(path);
} public synchronized void removeWatcher(Watcher watcher) {
//从watch2Paths和watchTable删除watcher
HashSet<String> paths = watch2Paths.remove(watcher);
if (paths == null) {
return;
}
for (String p : paths) {
HashSet<Watcher> list = watchTable.get(p);
if (list != null) {
list.remove(watcher);
if (list.size() == 0) {
watchTable.remove(p);
}
}
}
}
//触发watcher
public Set<Watcher> triggerWatch(String path, EventType type, Set<Watcher> supress) {
WatchedEvent e = new WatchedEvent(type,
KeeperState.SyncConnected, path);
HashSet<Watcher> watchers;
synchronized (this) {
//zookeeper的通知是一次性的,也就是说如果一个路径触发通知后,相应的watcher会从这两个hashmap中删除。
watchers = watchTable.remove(path);
for (Watcher w : watchers) {
HashSet<String> paths = watch2Paths.get(w);
if (paths != null) {
paths.remove(path);
}
}
}
for (Watcher w : watchers) {
if (supress != null && supress.contains(w)) {
continue;
}
w.process(e);
}
return watchers;
}
}
临时节点
zookeeper中有一类节点在创建的session结束后会被清除掉,zookeeper在创建这些节点时会记录节点和session 的对应关系,到session结束是,删除这些节点。
结束session(DataTree.killSession)
//session与零时节点对应关系
private final Map<Long, HashSet<String>> ephemerals =
new ConcurrentHashMap<Long, HashSet<String>>();
//关闭session
void killSession(long session, long zxid) {
//session结束后,删除零时节点
HashSet<String> list = ephemerals.remove(session);
if (list != null) {
for (String path : list) {
try {
deleteNode(path, zxid);
} catch (NoNodeException e) {
LOG.warn("Ignoring NoNodeException for path " + path
+ " while removing ephemeral for dead session 0x"
+ Long.toHexString(session));
}
}
}
}
权限管理
zookeeper的每个节点都会存储该节点可以访问的用户已经可以执行的操作。
权限(ACL)
public class ACL implements Record {
//perms即权限,有五种权限:READ(可读);WRITE(可写);CREATE(可创建子节点);DELETE(可删除子节点);ADMIN(管理权限);perms的每一位代表一种权限。
private int perms;
//id是授权的对象。
private org.apache.zookeeper.data.Id id;
}
public class Id implements Record {
//scheme是权限模式,有五种模式:digest(通过用户名密码,id为user:password);auth();ip(通过ip,id为ip地址);world(固定用户为anyone,为所有Client端开放权限 );super(对应的id拥有超级权限)。
private String scheme;
private String id;
}
每个节点可以设置多个权限,实际节点权限只存储一个整数,对应的acl信息保存在两个hashmap中。(DataTree.java)
public final Map<Long, List<ACL>> longKeyMap = new HashMap<Long, List<ACL>>();
public final Map<List<ACL>, Long> aclKeyMap = new HashMap<List<ACL>, Long>();
节点操作
zookeeper(2) 文件系统的更多相关文章
- Hadoop学习笔记—14.ZooKeeper环境搭建
从字面上来看,ZooKeeper表示动物园管理员,这是一个十分奇妙的名字,我们又想起了Hadoop生态系统中,许多项目的Logo都采用了动物,比如Hadoop采用了大象的形象,所以我们可以猜测ZooK ...
- zookeeper能做什么?
Zookeeper是Hadoop的一个子项目,虽然源自hadoop,但是我发现zookeeper脱离hadoop的范畴开发分布式框架的运用越来越多.今天我想谈谈zookeeper,本文不谈如何使用zo ...
- Zookeeper的功能以及工作原理
1.ZooKeeper是什么?ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,它是集群的管理者,监视着集群中各个节点的状态根据节点提交的 ...
- zookeeper系列之六—zookeeper之应用
http://www.cnblogs.com/sharpxiajun/archive/2013/06/02/3113923.html Zookeeper是hadoop的一个子项目,虽然源自hadoop ...
- 分布式服务框架:Zookeeper
Zookeeper是一个高性能,分布式的,开源分布式应用协调服务.它提供了简单原始的功能,分布式应用可以基于它实现更高级的服务,比如同步,配置管理,集群管理,名空间.它被设计为易于编程,使用文件系统目 ...
- 分布式网站架构后续:zookeeper技术浅析
Zookeeper是hadoop的一个子项目,虽然源自hadoop,但是我发现zookeeper脱离hadoop的范畴开发分布式框架的运用 越来越多.今天我想谈谈zookeeper,本文不谈如何使用z ...
- 七:zookeeper与paxos的分析
zookeeper是什么 官方说辞:Zookeeper 分布式服务框架是Apache Hadoop 的一个子项目,它主要是用来解决分布式应用中经常遇到的一些数据管理问题,如:统一命名服务.状态同步服务 ...
- zookeeper入门必读
(如果感觉有帮助,请帮忙点推荐,添加关注,谢谢!你的支持是我不断更新文章的动力.本博客会逐步推出一系列的关于大型网站架构.分布式应用.设计模式.架构模式等方面的系列文章) 今天我想谈谈zookeepe ...
- zookeeper使用场景【转】
分布式网站架构后续:zookeeper技术浅析 Zookeeper是hadoop的一个子项目,虽然源自hadoop,但是我发现zookeeper脱离hadoop的范畴开发分布式框架的运用越来越多. ...
随机推荐
- DNF手游公测或将只有安卓版 iOS系统怎么办?
DNF手游在8月10号确定延期后,目前还不知道新的上线时间.玩家都很关心DNF手游新的公测时间,DNF手游官网的预约数据也是不断突破新高,最终突破了五千万!我们目前拿到的小道消息,DNF手游会在9月1 ...
- python 02 if while
1. if的格式 >>> 1<3 True 真>>> 1>3False 假 if 条件: 条件 + : (t ...
- Spring配置文件中bean标签中init-method和destroy-method和用注解方式配置
Person类: public class Person { private int i = 0; public Person(){ System.o ...
- Python 抓包程序(pypcap)
#/usr/bin/env python #-*-coding:utf8-*- #抓包脚本 """ This script is used to Capture and ...
- scp 转
linux之cp/scp命令 名称:cp 使用权限:所有使用者 使用方式: cp [options] source dest cp [options] source... directory 说明 ...
- HTTP基础 --响应
响应,由服务端返回给客户端,分为三部分:响应状态码(Response Status Code),响应头(Response Headers)和响应体(Response Body). 响应状态码 响应服务 ...
- WS以及NW小世界网络的生成(MATLAB)
WS小世界网络生成算法,一般小世界网络生成算法速度慢,节点度分布与数学推导不符,在网络仿真中造成不便,这里针对实际网络动力学仿真过程撰写了WS小世界网络的MATLAB生成算法,并考虑了矩阵化,具有较高 ...
- 全国大学生信息安全竞赛初赛writeup
本文首发于“合天智汇”公众号 作者:Fortheone WEB Babyunserialize 扫目录发现了 www.zip 下载下来发现似曾相识 之前wmctf2020的webweb出了f3的反序列 ...
- spring mvc 国际化的几种方案
spring mvc 国际化的几种方案 首先配置我们项目的service-servlet.xml文件添加的内容如下: <bean id="messageSource" cla ...
- @RequestBody和@RequestParam
@RequestBody的使用 https://blog.csdn.net/justry_deng/article/details/80972817 (@RequestBody Map map)接收多 ...