设为首页 加入收藏

TOP

LevelDB源码之三SSTable(一)
2015-11-21 01:25:34 来源: 作者: 【 】 浏览:2
Tags:LevelDB 源码 之三 SSTable
上一节提到的MemTable是内存表,而当内存表增长到一定程度时(memtable.size> Options::write_buffer_size),会将当前的MemTable数据持久化(LevelDB中实际有两份MemTable,后面LevelDB 数据库备忘时会讲)。持久化的文件(sst文件)称之为Table,LevelDB中的Table分为不同的层级,当前版本的最大层级为7(0-6),table中level0的数据最新,level6的数据最旧。
?
Compaction动作负责触发内存表到SSTable的转换,LOG恢复时也会执行,这里不关心Compaction或恢复的任何细节,后面会单独备忘。
?
?
LevelDB通过BuildTable方法完成SSTable的构建,其创建SSTable文件并将memtable中的记录依次写入文件。BuildTable带了一个输出参数,FileMetaData:
?
 1     struct FileMetaData {
 2         int refs;
 3         int allowed_seeks;          // Seeks allowed until compaction
 4         uint64_t number;
 5         uint64_t file_size;         // File size in bytes
 6         InternalKey smallest;       // Smallest internal key served by table
 7         InternalKey largest;        // Largest internal key served by table
 8 
 9         FileMetaData() : refs(0), allowed_seeks(1 << 30), file_size(0) { }
10     };

?

number为一个递增的序号,用于创建文件名,allowed_seeks作者有提到,是当前文件在Compaction到下一级之前允许Seek的次数,这个次数和文件大小相关,文件越大,Compaction之前允许Seek的次数越多,这个Version备忘时也会提。
?
?
?
BuildTable方法中真正做事的时TableBuilder,通过调用Add方法将所有记录添加到数据表中,完成SSTable创建。
?
TableBuilder主要做了如下几件事:
?
创建Index Block:用于Data Block的快速定位
将数据分为一个个的Data Block
如文件需要压缩,执行压缩动作
依次写入Data Block、Meta Block、Index Block、Footer Block,形成完整的SSTable文件结构
其中阶段1-3由Add方法完成,阶段4由Finish方法完成,先来看Add方法:
?
?
 1 void TableBuilder::Add(const Slice& key, const Slice& value) {
 2         Rep* r = rep_;
 3         assert(!r->closed);
 4         if (!ok()) return;
 5         if (r->num_entries > 0) {
 6             assert(r->options.comparator->Compare(key, Slice(r->last_key)) > 0);
 7         }
 8 
 9         //Index Block:Data Block的索引元数据。
10         if (r->pending_index_entry) {
11             assert(r->data_block.empty());
12             r->options.comparator->FindShortestSeparator(&r->last_key, key);
13             std::string handle_encoding;
14             r->pending_handle.EncodeTo(&handle_encoding);
15             r->index_block.Add(r->last_key, Slice(handle_encoding));
16             r->pending_index_entry = false;
17         }
18 
19         r->last_key.assign(key.data(), key.size());
20         r->num_entries++;
21         r->data_block.Add(key, value);
22 
23         const size_t estimated_block_size = r->data_block.CurrentSizeEstimate();
24         if (estimated_block_size >= r->options.block_size) {
25             Flush();    //超过单数据块大小,写入文件。
26         }
27     }

?

?
Add方法创建Data Block、IndexBlock,DataBlcok通过Flush刷入磁盘文件。
?
再来看Finish方法:
?
?
 1     Status TableBuilder::Finish() {
 2         //Data Block
 3         Rep* r = rep_;
 4         Flush();
 5 
 6         assert(!r->closed);
 7         r->closed = true;
 8         
 9         //Meta Block
10         BlockHandle metaindex_block_handle;
11         BlockHandle index_block_handle;
12         if (ok()) 
13         {
14             BlockBuilder meta_index_block(&r->options);
15             // TODO(postrelease): Add stats and other meta blocks
16             WriteBlock(&meta_index_block, &metaindex_block_handle);
17         }
18 
19         //Index Block
20         if (ok()) {
21             if (r->pending_index_entry) {
22                 r->options.comparator->FindShortSuccessor(&r->last_key);
23                 std::string handle_encoding;
24                 r->pending_handle.EncodeTo(&handle_encoding);
25                 r->index_block.Add(r->last_key, Slice(handle_encoding));
26                 r->pending_index_entry = false;
27             }
28             WriteBlock(&r->index_block, &index_block_handle);
29         }
30 
31         //Footer
32         if (ok()) 
33         {
34             Footer footer;
35             footer.set_metaindex_handle(metaindex_block_handle);    //
36             footer.set_index_handle(index_block_handle);
37             std::string footer_encoding;
38
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇合服测试(一) 下一篇plsql+绿色版oracle连接远程数据..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: