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的范畴开发分布式框架的运用越来越多. ...
随机推荐
- 解决VS Code安装golang相关插件失败问题
解决VS Code安装golang相关插件失败问题 VSCode作为一款优秀的编辑器,基本上前端开发,Python,markdown都可以用,真正是开发过程中的好帮手,所以学习go也当仁不让的要用vs ...
- Ubuntu 下查看CPU 信息命令
from: http://hi.baidu.com/hermitinhistory/blog/item/ce64d5fb6b23b71b6d22eb95.html 查看当前操作系统内核信息 uname ...
- 焦大:逛网seo案例浅析
http://www.wocaoseo.com/thread-93-1-1.html 逛,发现喜欢.这或许是很多人上网的喜欢方式,我隐约记得白鸦在一次采访上说到现在人的购物方式,在淘宝上人们决定买一件 ...
- python编写汉诺塔 Hanoi
#hanoi.py count = 0 def hanoi(n, src, dst, mid): #src为原1号柱子 dst 目标3号柱子 mid中间2号过渡柱子 global count #对全局 ...
- e3mall商城总结11之sso系统的分析、应用以及解决ajax跨域问题
说在前面的话 一.sso系统分析 什么是sso系统 SSO英文全称Single Sign On,单点登录.SSO是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统.它包括可以将这次 ...
- Centos7安装Oracle12c教程
12c数据库 创建oracle的系统用户和用户组 [root@localhost /]# groupadd oinstall [root@localhost /]# groupadd dba [roo ...
- Flink从入门到入土(详细教程)
和其他所有的计算框架一样,flink也有一些基础的开发步骤以及基础,核心的API,从开发步骤的角度来讲,主要分为四大部分 1.Environment Flink Job在提交执行计算时,需要首先建立和 ...
- SpringBoot事务使用和回滚
Springboot中事务的使用: 1.启动类加上@EnableTransactionManagement注解,开启事务支持(其实默认是开启的). 2.在使用事务的public(只有public支持事 ...
- unity webview
uniwebview http://uniwebview.onevcat.com/manual Unity3D研究院之在Android中打开WebView(三十) http://www.xuanyus ...
- C# OWC11
public void OcwChart(int[] Data,string[] DataName,string Yname,string Xname,string ChartName,string ...