ZKDatabase在内存中维护了zookeeper的sessions, datatree和commit logs集合。 当zookeeper server启动的时候会将txnlogs和snapshots从磁盘读取到内存中。核心逻辑主要在方法ZkDatabase.loadDataBase()中实现,其代码如下:

    /**
* 将数据从磁盘加载到内存中,并将事物添加到内存中的提交日志中
* @return 磁盘上最后一个有效的zxid
* @throws IOException
*/
public long loadDataBase() throws IOException {
PlayBackListener listener=new PlayBackListener(){
public void onTxnLoaded(TxnHeader hdr,Record txn){
Request r = new Request(null, 0, hdr.getCxid(),hdr.getType(),
null, null);
r.txn = txn;
r.hdr = hdr;
r.zxid = hdr.getZxid();
addCommittedProposal(r);
}
}; long zxid = snapLog.restore(dataTree,sessionsWithTimeouts,listener);
initialized = true;
return zxid;
}

loadDataBase的流程如下:

  • 构建一个PlayBackListener对象
  • snapshot的反序列,倒叙排目录下的snapshot文件,遍历查找出最新的那个有效snapshot文件进行反序列化到内存。snapshot的反序列后我们会知道snapshot最新的zxid叫做lastProcessedZxid, 这个lastProcessedZxid之前的事务操作,都成功执行并序列到snapshot中可恢复到内存,lastProcessedZxid之后的操作只有事务日志,不能直接通过snapshot恢复。

snapLog.restore实现如下:

    public long restore(DataTree dt, Map<Long, Integer> sessions,
PlayBackListener listener) throws IOException {
//从最近的快照中对数据树进行反序列化
snapLog.deserialize(dt, sessions);
//lastProcessedZxid+1从事务日志文件txnLog读取事务操作
FileTxnLog txnLog = new FileTxnLog(dataDir);
TxnIterator itr = txnLog.read(dt.lastProcessedZxid+1);
long highestZxid = dt.lastProcessedZxid;
TxnHeader hdr;
try {
while (true) {
//遍历TxnIterator,执行processTransaction方法,就是把事务操作在内存中在执行一遍把丢失的操作补回来
hdr = itr.getHeader();
if (hdr == null) {
//empty logs
return dt.lastProcessedZxid;
}
if (hdr.getZxid() < highestZxid && highestZxid != 0) {
LOG.error("{}(higestZxid) > {}(next log) for type {}",
new Object[] { highestZxid, hdr.getZxid(),
hdr.getType() });
} else {
highestZxid = hdr.getZxid();
}
try {
processTransaction(hdr,dt,sessions, itr.getTxn());
} catch(KeeperException.NoNodeException e) {
throw new IOException("Failed to process transaction type: " +
hdr.getType() + " error: " + e.getMessage(), e);
}
// 同时将事务操作通过PlayBackListener添加到commitedLog集合,commitedLog的事务操作在服务恢复的时候会同步到其他leaner server, 因为很有可能其他leaner server也没有及时的takesnapshot
listener.onTxnLoaded(hdr, itr.getTxn());
if (!itr.next())
break;
}
} finally {
if (itr != null) {
itr.close();
}
}
//返回最后的事务日志zxid给database,作为ZKDatabase的最新事物id
return highestZxid;
}

在zookeeperServer成功loadDatabase后,会及时主动的做一次takesnapshot操作来得到一份最新的内存影像。snapshot是内存数据的某个点一份影像,takeSnapshot操作还是很耗时,为了性能根据一下算法操作:

  • 创建在同步处理器SyncRequestProcessor
  • 100000/2 + random.nextInt(100000/2),这个十万是一个默认值可配置)计算出一个值,如果logCount大于这个值,就进行takeSnapshot操作

上面的算法存在一个问题, 那就是在非正常关机情况下,最新有效的那个snapshot并不是内存中最新的数据,所以需要利用txnLogs来把没有生成snapshot的操作在内存重新执行一边来恢复到非正常关闭服务那一刻内存情况。

Zookeeper原理分析之存储结构ZkDatabase的更多相关文章

  1. Zookeeper原理分析之存储结构Snapshot

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

  2. Zookeeper原理分析之存储结构TxnLog

    Zookeeper事物日志文件用于记录事物操作,如添加,删除节点等等,都会在事务日志中记录一条记录.下面我们就详细分析一下txnLog事务日志文件. txnLog事务日志文件文件由三部分组成: 日志文 ...

  3. 1.zookeeper原理解析-数据存储之Zookeeper内存结构

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

  4. zookeeper原理解析-数据存储

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

  5. Hadoop生态圈-Zookeeper的工作原理分析

    Hadoop生态圈-Zookeeper的工作原理分析 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.   无论是是Kafka集群,还是producer和consumer都依赖于Zoo ...

  6. Hashtable数据存储结构-遍历规则,Hash类型的复杂度为啥都是O(1)-源码分析

    Hashtable 是一个很常见的数据结构类型,前段时间阿里的面试官说只要搞懂了HashTable,hashMap,HashSet,treeMap,treeSet这几个数据结构,阿里的数据结构面试没问 ...

  7. 牛客网Java刷题知识点之HashMap的实现原理、HashMap的存储结构、HashMap在JDK1.6、JDK1.7、JDK1.8之间的差异以及带来的性能影响

    不多说,直接上干货! 福利 => 每天都推送 欢迎大家,关注微信扫码并加入我的4个微信公众号:   大数据躺过的坑      Java从入门到架构师      人工智能躺过的坑          ...

  8. Zookeeper的基本原理(zk架构、zk存储结构、watch机制、独立安装zk、集群间同步复制)

    1.Hbase集群的高可用性与伸缩性 HBase可以实现对Regionserver的监控,当个别Regionserver不可访问时,将其负责的分区分给其他Regionsever,其转移过程较快,因为只 ...

  9. Atitit.数据索引 的种类以及原理实现机制 索引常用的存储结构

    Atitit.数据索引 的种类以及原理实现机制 索引常用的存储结构 1. 索引的分类1 1.1. 按照存储结构划分btree,hash,bitmap,fulltext1 1.2. 索引的类型  按查找 ...

随机推荐

  1. BZOJ1699: [Usaco2007 Jan]Balanced Lineup排队 - 线段树

    description 查询区间最大和最小 题解 线段树 愉悦身心啊 代码 #include<cstring> #include<cstdio> #include<alg ...

  2. TLS/SSL简单过程

    .wcf的认证分为两种 1.1 transport模式,在传输层完成认证(只能在传输层完成认证,利用硬件加速效率更高) a.在使用transport模式,非windows凭证的情况下默认使用TLS/S ...

  3. 网段;IP;广播地址;子网掩码;

    网段(network segment)一般指一个计算机网络中使用同一物理层设备(传输介质,中继器,集线器等)能够直接通讯的那一部分.例如,从192.168.0.1到192.168.255.255这之间 ...

  4. ST3 插件和技巧

    Emmet插件: 快速生成HTML文档结构, 快速编写跨浏览器的CSS并自动帮助你同时编辑, 强大! 语法技巧 简单实用, 值得掌握! SideBar Enhancements插件:  改进了侧边栏, ...

  5. Linux服务器上配置2个Tomcat或者多个Tomcat

    一.当在一个服务器上面安装2个tomcat的时候,修改第二个tomcat的conf目录下server.xml文件里面的端口号(原8080改成8081,原8005改成8006)可以达到两个tomcat都 ...

  6. 打开子页面及刷新父页面 window.open window.opener.reload()

    //打开子页面 var url=children_url;window.open(url) //刷新parent页面 var url=parent_urlfunction refresh(url){  ...

  7. ics

    5.网分用法 时延测试: Format ->Delay Scale Ref -> AUTO SCALE Marker Search -> TRACKING[ON OFF]这样以后把M ...

  8. spring mvc 静态资源版本控制

    spring bean 文件中增加 <bean class="cn.zno.smse.common.context.VersionServletContext">< ...

  9. Qt .pro文件 详解

    1. TEMPLATE变量TEMPLATE描述了为建立目标文件而采用何种模板,即生成何种形式的Makefile文件.Qmake工具定义了5种模板:1. 应用程序App,为建立一个Qt应用程序创建Mak ...

  10. Spring注解使用和与配置文件的关系

      Spring注解使用和与配置文件的关系 1 注解概述与容器管理机制 Spring 2.5 中除了提供 @Component 注释外,还定义了几个拥有特殊语义的注释,它们分别是:@Repositor ...