首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

zookeeper原理解析-数据存储(1)

zookeeper原理解析-数据存储(1)

Zookeeper内存结构Zookeeper是怎么存储数据的,什么机制保证集群中数据是一致性,在网络异常,当机以及停电等异常情况下恢复数据的,我们知道数据库给我们提供了这些功能,其实zookeeper也实现了类似数据库的功能。
1.      Zookeeper内存结构
         Zookeeper数据在内存中的结构类似于linux的目录结构

[url=][/url]
DataTree代表这个目录结构, DataNode代表一个节点         DataTree:                   默认初始化三目录                  1""          2) "/zookeeper"         3) "/zookeeper/quota"         DataNode                   表示一个节点                 1) 存储了父节点的引用                 2) 节点的权限信息                 3) 子节点路径集合[url=][/url]

Snapshot
Snapshot是datatree在内存中某一时刻的影像,zookeeper有一定的机制会定时生成datatree的snapshot。FileSnap实现了SnapShot接口负责将数据写入文件中,下面我们来看看snap相关内容。
2.1 snapshot文件格式
   Snapshot是以二进制形式存在在文件的,我们用ue打开一个新的snapshot文件


Snapshot文件的中数据大体可以分为两部分header和body。
Header数据格式:
FileHeader{   int magic  //魔数   常量ZKSN  代表zookeeper snapshot文件   int  version  //版本  常量 2   long   dbid   //dbid  常量 -1}

这里很奇怪 version和dbid都是常量,那还有什么意思,也许是保留字段为后续版本使用。

由头部字段可以计算出头部信息占用 4 + 4 + 8 =16bit的固定长度
5A 4B 53 4E 就是魔术ZKSN
00 00 00 02 就是dbid号2
FF FF FF FF FF FF FF FF就是十六进制的-1
[url=][/url]
public voidserialize(OutputArchive oa, String tag) throws IOException {        scount = 0;        serializeList(longKeyMap, oa);        serializeNode(oa, newStringBuilder(""));        if (root != null) {            oa.writeString("/","path");        }    }2.1)序列化longKeyMap是存储在datatree中的acl权限集合           readInt("map") //acl的映射个数?        while (map > 0) {            readLong("long") //这个long值longKeyMap的key,作用?是这一组acl的key         readInt("acls")         while (acls) {              readInt("perms")           readString("scheme")             readString("id")           }     }2.2)存储datatree中数据节点        readString("path")//第一个datanode ""    while(!path.equals("/")) {   //  "/"代表路径结束                  readRecord(node, "node")包括:           readBuffer("data")           readLong("acl")           deserialize(archive,"statpersisted") 状态存储包括:                          readLong("czxid")  //createNode时事务号                            readLong("mzxid")  //createNode时与Czxid同,setData时的事务号                            readLong("ctime")  // 创建节点时间                            readLong("mtime")  //createNode时与ctime相同,setData时间                            readInt("version")  //createNode版本为0,setData的数据版本号                            readInt("cversion") //createNode版本为0,增加/删除子节点时父节点+1                            readInt("aversion") //createNode版本为0,setACL时节点的版本号                            readLong("ephemeralOwner") // 临时节点表示sessionid,非临时节点这个值为0                            readLong("pzxid")  //createNode时与Czxid同,增加/删除子节点时为子节点事务号        readString("path") //读取下一个路径  }3)  文件尾部校验数据00 00 00 01 2F  snapshot文件结尾5位数据用来校验snapshot文件是否有效   00 00 00 01一个int的数值就是数字1,代表后面1一个字符数据   2F 就是snapshot的结束符/[url=][/url]

Body数据格式:
Snapshot文件中头部信息之后,紧接着就是body部分的信息,body数据大小是动态不是固定。
1) Map<Long, Integer> sessionWithTimeoutbody信息前面部分存储的是内存中活着的session以及session的超时时间

oa.writeInt(sessSnap.size(),"count");

        for (Entry<Long, Integer> entry :sessSnap.entrySet()) {

           oa.writeLong(entry.getKey().longValue(), "id");

            oa.writeInt(entry.getValue().intValue(),"timeout");

        }

由上面序列到文件代码可以看出先写入一个int类型字段用来存储sessionWithTimeout的个数,然后在遍历集合以一个long一个int的形式写入
2) 紧接着就是对datatree序列化到文件了
返回列表