leveldb源码分析--SSTable之TableBuilder
上一篇文章讲述了SSTable的格式以后,本文结合源码解析SSTable是如何生成的。
void TableBuilder::Add(const Slice& key, const Slice& value) { //如果已经插入过数据,那么要保证当前插入的key > 之前最后一次插入的key,
// SSTable必须是有序的插入数据 if (r->num_entries > ) {
assert(r->options.comparator->Compare(key, Slice(r->last_key)) > );
} //新的block
if (r->pending_index_entry) {
//找到前一个block和当前key之间的最短的字符串作为block分界Key,作为块索引
r->options.comparator->FindShortestSeparator(&r->last_key, key);
r->pending_handle.EncodeTo(&handle_encoding); //将找到的shortest key 和encode后的块索引加入索引块中
r->index_block.Add(r->last_key, Slice(handle_encoding));
r->pending_index_entry = false;
} //如果使用了filter(leveldb中一般为bloomfilter
if (r->filter_block != NULL) {
r->filter_block->AddKey(key);
} //记录最后一次插入的key,插入数量,添加的数据块中 r->last_key.assign(key.data(), key.size());
r->num_entries++;
r->data_block.Add(key, value); //如果当前已插入的大小达到设定的block阈值,将block写到数据文件中
const size_t estimated_block_size = r->data_block.CurrentSizeEstimate(); if (estimated_block_size >= r->options.block_size) {
Flush();
}
}
函数Flush()主要是作一些基本的判断以后调用WriteBlock将数据写入文件并刷到磁盘,然后为下一个block新建一个filter段。仔细看看WriteBlock
void TableBuilder::WriteBlock(BlockBuilder* block, BlockHandle* handle) {
//调用block的Finish将block组码为一个内存段,block_builder的内容稍后分析
Slice raw = block->Finish(); // 根据压缩类型压缩
switch (type) {
case kNoCompression:
block_contents = raw;
break; case kSnappyCompression: {
std::string* compressed = &r->compressed_output; //如果压缩后的大小比原始大小的7/8小(压缩率12.5%以上),则压缩,否则写入原始数据
if (port::Snappy_Compress(raw.data(), raw.size(), compressed) &&
compressed->size() < raw.size() - (raw.size() / 8u)) {
block_contents = *compressed;
} else {
block_contents = raw;
type = kNoCompression;
}
break;
}
}
//将内容写入文件,格式为(block_data,type,crc)
WriteRawBlock(block_contents, type, handle);
}
Status TableBuilder::Finish() 将当前SSTable的数据写完以后的一些Meta信息的写入,也即数据文件的管理信息的写入,这一部分数据是SSTable中非常关键的一部分数据,我们来看他的写入过程。
Status TableBuilder::Finish() { //先将data_block内容写到文件
Flush(); // 写filterblock也即为Metablock记录的filter信息,具体分析稍后再filterblock中专门分析
if (ok() && r->filter_block != NULL) {
WriteRawBlock(r->filter_block->Finish(), kNoCompression,
&filter_block_handle);
} // 写入metablock的index,包含一个key=filter.filter名,value=开始的filter_block的handle
if (ok()) {
BlockBuilder meta_index_block(&r->options);
if (r->filter_block != NULL) {
std::string key = "filter.";
key.append(r->options.filter_policy->Name());
std::string handle_encoding;
filter_block_handle.EncodeTo(&handle_encoding);
meta_index_block.Add(key, handle_encoding);
}
// 写入文件中
WriteBlock(&meta_index_block, &metaindex_block_handle);
} // 写data_block的索引块,之前每个data_block会取一个FindShortestSeparator作为key,
// value为该block的block_handle,最后一块的key为FindShortSuccessor
if (ok()) {
if (r->pending_index_entry) {
r->options.comparator->FindShortSuccessor(&r->last_key);
std::string handle_encoding;
r->pending_handle.EncodeTo(&handle_encoding);
r->index_block.Add(r->last_key, Slice(handle_encoding));
r->pending_index_entry = false;
}
WriteBlock(&r->index_block, &index_block_handle);
} // 写footer块,包括了MetaIndex block和Indexblock 的BlockHandle,以及填充区和一个magic数字
if (ok()) {
Footer footer;
footer.set_metaindex_handle(metaindex_block_handle);
footer.set_index_handle(index_block_handle);
footer.EncodeTo(&footer_encoding);
r->status = r->file->Append(footer_encoding);
if (r->status.ok()) {
r->offset += footer_encoding.size();
}
}
return r->status;
}
知道了table_builder的各个函数的处理流程以后,我们自然会想这些函数是在什么地方调用的呢?什么地方初始化的呢?通过阅读代码我们可以知道build SSTable都是在compaction的时候进行的,为compact memtable和SSTable的时候都会调用到。其中compact memtable是在builder.cc的BuildTable中,而compact SSTable则是在DoCompactionWork中。BuildTable逻辑简单,这里就不再进行解释,推荐读者先阅读这个流程,以认识生成一个SSTable 的过程。而DoCompactionWork由于涉及到更多的compaction相关的内容,这个我们在后面解释compaction的时候再专门介绍。
leveldb源码分析--SSTable之TableBuilder的更多相关文章
- leveldb源码分析--SSTable之block
在SSTable中主要存储数据的地方是data block,block_builder就是这个专门进行block的组织的地方,我们来详细看看其中的内容,其主要有Add,Finish和CurrentSi ...
- LevelDB源码分析-sstable的Block
sstable中的Block(table/block.h table/block.cc table/block_builder.h table/block_builder.cc) sstable中的b ...
- leveldb源码分析--SSTable之Compaction
对于compaction是leveldb中体量最大的一部分,也应该是最为复杂的部分,为了便于理解我们首先从一些基本的概念开始.下面是一些从doc/impl.html中翻译和整理的内容: Level 0 ...
- leveldb源码分析--SSTable之逻辑结构
SSTable是leveldb 的核心模块,这也是其称为leveldb的原因,leveldb正是通过将数据分为不同level的数据分为对应的不同的数据文件存储到磁盘之中的.为了理解其机制,我们首先看看 ...
- Leveldb源码分析--1
coming from http://blog.csdn.net/sparkliang/article/details/8567602 [前言:看了一点oceanbase,没有意志力继续坚持下去了,暂 ...
- leveldb源码分析--WriteBatch
从[leveldb源码分析--插入删除流程]和WriteBatch其名我们就很轻易的知道,这个是leveldb内部的一个批量写的结构,在leveldb为了提高插入和删除的效率,在其插入过程中都采用了批 ...
- leveldb源码分析--Key结构
[注]本文参考了sparkliang的专栏的Leveldb源码分析--3并进行了一定的重组和排版 经过上一篇文章的分析我们队leveldb的插入流程有了一定的认识,而该文设计最多的又是Batch的概念 ...
- leveldb源码分析--日志
我们知道在一个数据库系统中为了保证数据的可靠性,我们都会记录对系统的操作日志.日志的功能就是用来在系统down掉的时候对数据进行恢复,所以日志系统对一个要求可靠性的存储系统是极其重要的.接下来我们分析 ...
- leveldb源码分析之Slice
转自:http://luodw.cc/2015/10/15/leveldb-02/ leveldb和redis这样的优秀开源框架都没有使用C++自带的字符串string,redis自己写了个sds,l ...
随机推荐
- vue父组件传参给子组件
其实组件之间传参有很多种方法: 1.通过本地存储 2.使用vuex状态管理 今天记录一下第三种方法 1.首页我们先创建一个项目(创建项目自行百度) 2.打开项目,在components文件夹下新建一个 ...
- 哨兵/sentinel:在算法设计中的应用
哨兵(sentinel)昨天看算法导论里对哨兵的描述后,觉得这是一种很有意思的编程思想.哨兵是一个哑对象.一般哨兵不存放任何数据,但其结构体与其他有用的元素一致.正如其字面意思,哨兵是在边界保卫祖国的 ...
- JAVA多线程Thread VS Runnable详解
要求 必备知识 本文要求基本了解JAVA编程知识. 开发环境 windows 7/EditPlus 演示地址 源文件 进程与线程 进程是程序在处理机中的一次运行.一个进程既包括其所要执行的指令,也 ...
- Ajax初始接触
演示JS对象的属性,方法和事件的使用 (1)window.location.href (2)form.submit() <form action="" method=&quo ...
- 29-hadoop-使用phtonenix工具&分页&数据导入
因为rowkey一般有业务逻辑, 所以不可以直接使用rowkey进行分页, startkey, endkey 想要使用SQL语句对Hbase进行查询,需要使用Apache的开源框架Phoenix. 安 ...
- (转)Spring常见注解总结
传统的Spring做法是使用.xml文件来对bean进行注入或者是配置aop.事物,这么做有两个缺点: 1.如果所有的内容都配置在.xml文件中,那么.xml文件将会十分庞大:如果按需求分开.xml文 ...
- Eclipse 处理 Console 打印信息自动删除
开发中,特识是需要项目运行打印日志很长的时候需要查看打印的日志, Eclipse没经过设定的话,会自动80000行之前的日志记录. 想要日志一直打印下去处理方法: Preferences --> ...
- 开源方案搭建可离线的精美矢量切片地图服务-6.Mapbox之.pbf字体库
项目成果展示(所有项目文件都在阿里云的共享云虚拟主机上,访问地图可以会有点慢,请多多包涵). 01:中国地图:http://test.sharegis.cn/mapbox/html/3china.ht ...
- ApiGen 4.0配置项
Usage: generate [-s|--source="..."] [-d|--destination="..."] [--access-levels=&q ...
- zoj 2818 Root of the Problem(数学思维题)
题目链接: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2818 题目描述: Given positive integer ...