IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> zookeeper源码解析(一) -> 正文阅读

[数据结构与算法]zookeeper源码解析(一)

2021SC@SDUSC?

从ZKDatabase说起

ZKDatabase类维护着zookeeper的内存数据库,具体包括了数据树,会话信息和事务提交日志等。

首先,我们不妨来看一下ZKDatabase类的静态变量和成员变量。

    //为该类创建日志记录器
    private static final Logger LOG = LoggerFactory.getLogger(ZKDatabase.class);
    //要维护的四个成员变量
    protected DataTree dataTree;
    protected ConcurrentHashMap<Long, Integer> sessionsWithTimeouts;
    protected FileTxnSnapLog snapLog;
    protected long minCommittedLog, maxCommittedLog;

dataTree:维护了树形数据结构,不包含任何网络相关或客户端连接相关的代码。

sessionWithTimeouts:存储sessionID和对应的过期时间,使用并发哈希表ConcurrentHashMap作为变量类型,这是HashMap的一个线程安全的、支持高效并发的版本。

(PS:这里简单介绍一下sessionID和对应的过期时间的含义。

sessionID: 会话ID,用来唯一标识一个会话,每次客户端创建会话的时候,zookeeper 都会为其分配一个全局唯一的 sessionID。

Timeout:会话超时时间。客户端在构造 Zookeeper 实例时候,向服务端发送配置的超时时间,server 端会根据自己的超时时间限制最终确认会话的超时时间。)

snapLog:维护事务日志和数据快照,snapLog和具体的zookeeper数据库是一一对应的。

minCommittedLog,maxCommittedLog:zookeeper维护commitedLog队列,minCommittedLog和maxCommitedLog分别对应队列中事务编号的最小值和最大值(值得注意的是,zookeeper指定了这个队列有个默认最大长度500如下图,当队列更新要超过最大长度时,会移除目前队列中最早的事务)。

    public static final String COMMIT_LOG_COUNT = "zookeeper.commitLogCount";
    public static final int DEFAULT_COMMIT_LOG_COUNT = 500;
    public int commitLogCount;

PS:zookeeper的事务ID(zxid)遵循如下规则:

zxid是一个64位的数字,它高32位是epoch用来标识leader关系是否改变,每次一个leader被选出来,它都会有一个新的epoch,标识当前属于那个leader的统治时期。低32位用于递增计数。

DataTree-zookeeper数据库的核心

上面简单介绍了ZKDatabase类后,让我们先把焦点转到DataTree类。(我们先对ZKDatabase类中一个实例所要维护的这几个变量的结构做深入了解,之后再回到ZKDatabase类,看它提供了哪些函数哪些行为来维护这些变量)。DataTree无疑是zookeeper所构建的内存数据库的核心部分,其维护了一个树形数据结构。

DataTree主要维护两个结构,一个是各个绝对路径到数据节点的哈希表,另一个是由数据节点构成的树。并且对路径的所有访问是通过哈希表,仅在序列化到磁盘时遍历该树。如下成员变量nodes即存储着哈希表,是对哈希表的简单封装。

    //日志
    private static final Logger LOG = LoggerFactory.getLogger(DataTree.class);
    private final RateLogger RATE_LOGGER = new RateLogger(LOG, 15 * 60 * 1000);

    /**节点的哈希表,从绝对路径映射到数据节点。NodeHashMap是个接口,对这个接口,zookeeper
    实际上也就给出唯一一个实现类NodeHashMapImpl,它是对java提供的并发哈希表ConcurrentHash
    Map的一个简单封装
    */
    private final NodeHashMap nodes;
   
    //watch的管理(zookeeper通过watch对客户端提供了通知节点变化的机制)
    private IWatchManager dataWatches;
    private IWatchManager childWatches;

    //存储所有节点的路径及数据占的空间大小
    private final AtomicLong nodeDataSize = new AtomicLong(0);

    //zookeeper中树的根节点为"/"
    private static final String rootZookeeper = "/";

DataTree构造函数

    public DataTree() {
        this(new DigestCalculator());
    }

    DataTree(DigestCalculator digestCalculator) {
        this.digestCalculator = digestCalculator;
        nodes = new NodeHashMapImpl(digestCalculator);
        
        //添加根节点
        nodes.put("", root);
        nodes.putWithoutDigest(rootZookeeper, root);

        //分别添加配额节点和管理配额的节点
        root.addChild(procChildZookeeper);
        nodes.put(procZookeeper, procDataNode);

        procDataNode.addChild(quotaChildZookeeper);
        nodes.put(quotaZookeeper, quotaDataNode);

        addConfigNode();

        nodeDataSize.set(approximateDataSize());
        try {
            //配置监听器
            dataWatches = WatchManagerFactory.createWatchManager();
            childWatches = WatchManagerFactory.createWatchManager();
        } catch (Exception e) {
            LOG.error("Unexpected exception when creating WatchManager, exiting abnormally", e);
            ServiceUtils.requestSystemExit(ExitCode.UNEXPECTED_ERROR.getValue());
        }
    }

PS:关于配额,是指节点可以设置配额,如限制节点可以有几个子节点。但事实上,如果超过了配额限制,也只是在日志上会出现警告信息,实际内容还是被存储了。

这里把构造函数写成一个public,一个default,而public实际上基本只是调用default构造函数的形式我觉得可能仅仅是为了方便测试,事实上,在系统实现代码上都是调的public的构造函数,只有在测试代码中用到了default构造函数。

题外趣事?

在阅读源码的过程中,我发现即使是出自apache这样代码质量比较高的组织,代码中也会出现p,pp...这样的命名方式。

 

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-10-04 13:05:02  更:2021-10-04 13:05:43 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/17 10:26:11-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码