zk 文件存储
zk 有 2 种文件,快照和事务日志,快照是某一时刻的全量数据,事务日志中记录了数据的修改事件。
快照的文件名是 snapshot.zxid,zxid 是当前最大的事务 id
// org.apache.zookeeper.server.persistence.FileTxnSnapLog#save
public void save(DataTree dataTree,
ConcurrentHashMap<Long, Integer> sessionsWithTimeouts)
throws IOException {
long lastZxid = dataTree.lastProcessedZxid;
// 快照文件名为 snapshot.lastZxid
File snapshotFile = new File(snapDir, Util.makeSnapshotName(lastZxid));
LOG.info("Snapshotting: 0x{} to {}", Long.toHexString(lastZxid),
snapshotFile);
snapLog.serialize(dataTree, sessionsWithTimeouts, snapshotFile); }
事务日志的文件名是 log.zxid,zxid 是当前文件第一条日志的事务 id
// org.apache.zookeeper.server.persistence.FileTxnLog#append
public synchronized boolean append(TxnHeader hdr, Record txn)
throws IOException
{
if (hdr == null) {
return false;
} if (hdr.getZxid() <= lastZxidSeen) {
LOG.warn("Current zxid " + hdr.getZxid()
+ " is <= " + lastZxidSeen + " for "
+ hdr.getType());
} else {
lastZxidSeen = hdr.getZxid();
} if (logStream==null) {
if(LOG.isInfoEnabled()){
LOG.info("Creating new log file: " + Util.makeLogName(hdr.getZxid()));
}
// 创建一个新的事务日志文件 log.zxid,这里的 zxid 是第一条事务日志的 zxid
logFileWrite = new File(logDir, Util.makeLogName(hdr.getZxid()));
fos = new FileOutputStream(logFileWrite);
logStream=new BufferedOutputStream(fos);
oa = BinaryOutputArchive.getArchive(logStream);
FileHeader fhdr = new FileHeader(TXNLOG_MAGIC,VERSION, dbId);
fhdr.serialize(oa, "fileheader");
// Make sure that the magic number is written before padding.
logStream.flush();
filePadding.setCurrentSize(fos.getChannel().position());
streamsToFlush.add(fos);
}
filePadding.padFile(fos.getChannel());
byte[] buf = Util.marshallTxnEntry(hdr, txn);
if (buf == null || buf.length == 0) {
throw new IOException("Faulty serialization for header " +
"and txn");
}
Checksum crc = makeChecksumAlgorithm();
crc.update(buf, 0, buf.length);
oa.writeLong(crc.getValue(), "txnEntryCRC");
Util.writeTxnBytes(oa, buf); return true;
}
zk 加载数据:从 snap 文件和 log 文件解析出全量数据
// org.apache.zookeeper.server.persistence.FileTxnSnapLog#restore
public long restore(DataTree dt, Map<Long, Integer> sessions,
PlayBackListener listener) throws IOException {
snapLog.deserialize(dt, sessions);
return fastForwardFromEdits(dt, sessions, listener);
}
逆序选择 100 个 snap 文件,从最新的文件开始解析,如果有一个文件校验正确,则退出
public long deserialize(DataTree dt, Map<Long, Integer> sessions)
throws IOException {
// we run through 100 snapshots (not all of them)
// if we cannot get it running within 100 snapshots
// we should give up
List<File> snapList = findNValidSnapshots(100);
if (snapList.size() == 0) {
return -1L;
}
File snap = null;
boolean foundValid = false;
for (int i = 0; i < snapList.size(); i++) {
snap = snapList.get(i);
InputStream snapIS = null;
CheckedInputStream crcIn = null;
try {
LOG.info("Reading snapshot " + snap);
snapIS = new BufferedInputStream(new FileInputStream(snap));
crcIn = new CheckedInputStream(snapIS, new Adler32());
InputArchive ia = BinaryInputArchive.getArchive(crcIn);
deserialize(dt, sessions, ia);
long checkSum = crcIn.getChecksum().getValue();
long val = ia.readLong("val");
if (val != checkSum) {
throw new IOException("CRC corruption in snapshot : " + snap);
}
foundValid = true;
break;
} catch(IOException e) {
LOG.warn("problem reading snap file " + snap, e);
} finally {
if (snapIS != null)
snapIS.close();
if (crcIn != null)
crcIn.close();
}
}
if (!foundValid) {
throw new IOException("Not able to find valid snapshots in " + snapDir);
}
dt.lastProcessedZxid = Util.getZxidFromName(snap.getName(), SNAPSHOT_FILE_PREFIX);
return dt.lastProcessedZxid;
}
对比已经解析出的最大 zxid,选择对应的 log 文件
// org.apache.zookeeper.server.persistence.FileTxnLog.FileTxnIterator#init
void init() throws IOException {
storedFiles = new ArrayList<File>();
List<File> files = Util.sortDataDir(FileTxnLog.getLogFiles(logDir.listFiles(), 0), LOG_FILE_PREFIX, false);
for (File f: files) {
if (Util.getZxidFromName(f.getName(), LOG_FILE_PREFIX) >= zxid) {
storedFiles.add(f);
}
// add the last logfile that is less than the zxid
else if (Util.getZxidFromName(f.getName(), LOG_FILE_PREFIX) < zxid) {
storedFiles.add(f);
break;
}
}
goToNextLog();
if (!next())
return;
while (hdr.getZxid() < zxid) {
if (!next())
return;
}
}
zk 文件存储的更多相关文章
- Kafka与RocketMq文件存储机制对比
一个商业化消息队列的性能好坏,其文件存储机制设计是衡量一个消息队列服务技术水平和最关键指标之一. 开头问题 kafka文件结构和rocketMQ文件结构是什么样子?特点是什么? 一.目录结构 Kafk ...
- Android数据存储之Android 6.0运行时权限下文件存储的思考
前言: 在我们做App开发的过程中基本上都会用到文件存储,所以文件存储对于我们来说是相当熟悉了,不过自从Android 6.0发布之后,基于运行时权限机制访问外置sdcard是需要动态申请权限,所以以 ...
- 深入理解Sqlserver文件存储之页和应用 (转)
我们每天都在使用数据库,我们部门使用最多的关系数据库有Sqlserver,Oracle,有没有想过这些数据库是怎么存放到操作系统的文件中的?有时候为了能够设计出最优的表结构,写出高性能的Sqlserv ...
- app端上传文件至服务器后台,web端上传文件存储到服务器
1.android前端发送服务器请求 在spring-mvc.xml 将过滤屏蔽(如果不屏蔽 ,文件流为空) <!-- <bean id="multipartResolver&q ...
- MongoDb gridfs-ngnix文件存储方案
在各类系统应用服务端开发中,我们经常会遇到文件存储的问题. 常见的磁盘文件系统,DBMS传统文件流存储.今天我们看一下基于NoSQL数据库MongoDb的存储方案.笔者环境 以CentOS ...
- Hadoop中pid文件存储
我的hadoop集群部署在自己电脑虚拟机上,有时候我是挂起虚拟机,第二天再打开发现有些线程就挂了,比如namenode,好奇怪,当时看了一些帖子说是和pid存储有关,找到log看到找不到pid.因为基 ...
- Android文件存储
文件存储是Android中最基本的一种数据存储方式,它不读存储的内容进行任何的格式化处理,所有数据原封不动的保存在文件之中.如果想用文件存储的方式保存一些较为复杂的数据,就需要定义一套自己的格式规范, ...
- Kafka深入理解-1:Kafka高效的文件存储设计
文章摘自:美团点评技术团队 Kafka文件存储机制那些事 Kafka是什么 Kafka是最初由Linkedin公司开发,是一个分布式.分区的.多副本的.多订阅者,基于zookeeper协调的分布式日 ...
- .Net平台下,分布式文件存储的实现
遇到的问题 对于Web程序,使用一台服务器的时候,客户端上传的文件一般也都是存储在这台服务器上.但在集群环境中就行不通了,如果每个服务器都存储自己接受到的文件,就乱套了,数据库中明明有这个附件的记录, ...
随机推荐
- 31、NTP时间服务器
1.NTP简介 NTP服务器顾名思义就是时间同步服务器(Network Time Protocol),Linux下的ntp服务器配置相对来说都比较容易,但在Linux下有一个弊端,不同时区或者说是时间 ...
- 能ping通某网页,但无法访问网页的处理
cmd----->netsh winsock reset 用以重置Winsock目录,是网络环境初始化,解决一些奇怪的问题
- java8学习之Collector同一性与结合性分析
继续沿着上一次[http://www.cnblogs.com/webor2006/p/8311074.html]Collector接口的javadoc进行阅读,在继续阅读之前,其中有个比较难理解的地方 ...
- WIndows cmd command 指令总结
1. 文件操作 显示当前文件夹内所有文件 dir dir /s 仅显示特定后缀的文件 # 查找当前目录下所有mp3文件dir /s *.mp3
- C++最快获取像素值
HDC hdc, hdcTemp; RECT rect; BYTE* bitPointer; int x, y; int red, green, blue, alpha; while(true) { ...
- 使用xpath提取页面所有a标签的href属性值
# -*- coding: utf-8 -*- #1.选取节点 #获取所有的div元素 //div #/代表获取根节点的直接子元素 #获取所有带有id属性的div //div[@id] #2.谓词(索 ...
- qt5--QPainter绘图
需要 #include <QPainter> #include "win.h" #include "ui_win.h" #include <Q ...
- qt5---QMainWindow
QMainWindow是一个为用户提供主窗口程序的类,包含一个菜单栏(menu bar).多个工具栏(tool bars).多个锚接部件(dock widgets)[就是浮动窗口].一个状态栏(sta ...
- C/C++数据类型判断与转换
最近总想着写一些通用的代码,然集中收纳到自己的私人库中去,这些代码期望能与公司基础数据结构无关.然而这比较难,因为无论如何,必需要用到一些结构 化的东西,这些与基础引擎等有关,必需极度抽象才可以做到层 ...
- chomre 控制台断点调试
在上图蓝色圆圈中数字,它们分别代表: 1.停止断点调试 2.不跳入函数中去,继续执行下一行代码(F10) 3.跳入函数中去(F11) 4.从执行的函数中跳出 5.禁用所有的断点,不做任何调试 6.程序 ...