zoukankan      html  css  js  c++  java
  • Zookeeper原理分析之存储结构Snapshot

    Zookeeper内存结构

    Zookeeper数据在内存中的结构类似于linux的目录结构,DataTree代表这个目录结构, DataNode代表一个节点。DataTree默认初始化三个目录:"","/zookeeper","/zookeeper/quota"

    DataNode表示一个节点,存储了一下信息:

    • 父节点的引用
    • 节点的权限集合
    • 子节点路径集合

    Snapshot

    Snapshot是datatree在内存中某一时刻的快照,zookeeper有一定的机制会定时生成datatree的snapshot。FileSnap实现了SnapShot接口负责将数据写入文件中。

    snapshot文件格式

    Snapshot是以二进制形式存在在文件的,Snapshot文件的中数据大体可以分为两部分header和body。

    Header数据格式:

    public class FileHeader implements Record {
      private int magic;//魔数   常量ZKSN  代表zookeeper snapshot文件
      private int version;//版本 常量2
      private long dbid;//常量 -1
    }
    

    由头部字段可以计算出头部信息占用 4 + 4 + 8 =16bit的固定长度,5A 4B 53 4E 就是魔术ZKSN,00 00 00 02 就是dbid号2,FF FF FF FF FF FF FF FF就是十六进制的-1

    body数据格式

    Snapshot文件中头部信息之后,紧接着就是body部分的信息,body数据大小是动态的,其存储分为两部分:

    • Map<Long, Integer> sessionWithTimeoutbody信息前面部分存储的是内存中活着的session以及session的超时时间
    	public static void serializeSnapshot(DataTree dt,OutputArchive oa,
                Map<Long, Integer> sessions) throws IOException {
            HashMap<Long, Integer> sessSnap = new HashMap<Long, Integer>(sessions);
            oa.writeInt(sessSnap.size(), "count");
            for (Entry<Long, Integer> entry : sessSnap.entrySet()) {
                oa.writeLong(entry.getKey().longValue(), "id");
                oa.writeInt(entry.getValue().intValue(), "timeout");
            }
            dt.serialize(oa, "tree");
        }
    

    由上面序列到文件代码可以看出先写入一个int类型字段用来存储sessionWithTimeout的个数,然后在遍历集合以一个long一个int的形式写入,表示sessionid和过期时间

    • 把datatree序列化到文件中
        public void serialize(OutputArchive oa, String tag) throws IOException {
            scount = 0;
            serializeList(longKeyMap, oa);
            serializeNode(oa, new StringBuilder(""));
            // / marks end of stream
            // we need to check if clear had been called in between the snapshot.
            if (root != null) {
                oa.writeString("/", "path");
            }
        }
    

    上述代码中的longKeyMap是存储在datatree中的acl权限集合,序列化方式如下:

        private synchronized void serializeList(Map<Long, List<ACL>> longKeyMap,
                OutputArchive oa) throws IOException {
            oa.writeInt(longKeyMap.size(), "map");
            Set<Map.Entry<Long, List<ACL>>> set = longKeyMap.entrySet();
            for (Map.Entry<Long, List<ACL>> val : set) {
                oa.writeLong(val.getKey(), "long");
                List<ACL> aclList = val.getValue();
                oa.startVector(aclList, "acls");
                for (ACL acl : aclList) {
                    acl.serialize(oa, "acl");
                }
                oa.endVector(aclList, "acls");
            }
        }
    

    serializeNode表示序列化DataTree中的node节点

        void serializeNode(OutputArchive oa, StringBuilder path) throws IOException {
            String pathString = path.toString();
            DataNode node = getNode(pathString);
            if (node == null) {
                return;
            }
            String children[] = null;
            synchronized (node) {
                scount++;
                oa.writeString(pathString, "path");
                oa.writeRecord(node, "node");
                Set<String> childs = node.getChildren();
                if (childs != null) {
                    children = childs.toArray(new String[childs.size()]);
                }
            }
            path.append('/');
            int off = path.length();
            if (children != null) {
                for (String child : children) {
                    // since this is single buffer being resused
                    // we need
                    // to truncate the previous bytes of string.
                    path.delete(off, Integer.MAX_VALUE);
                    path.append(child);
                    serializeNode(oa, path);
                }
            }
        }
    

    文件尾部校验数据

    00 00 00 01 2F snapshot文件结尾5位数据用来校验snapshot文件是否有效

    00 00 00 01一个int的数值就是数字1,代表后面1一个字符数据

    2F 就是snapshot的结束符/

  • 相关阅读:
    HDU 1284 思维上的水题
    Buy Tickets POJ
    K-th Number Poj
    主席树入门+博客推荐
    Greg and Array CodeForces 296C 差分数组
    三连击 P1008 洛谷 python写法
    Lost Cows POJ 2182 思维+巧法
    Bash and a Tough Math Puzzle CodeForces 914D 线段树+gcd数论
    Can you answer these queries? HDU 4027 线段树
    敌兵布阵 HDU 1166 线段树
  • 原文地址:https://www.cnblogs.com/senlinyang/p/8408743.html
Copyright © 2011-2022 走看看