一、db_impl.cc分析
- 调用WriteLevel0Table把Memtable落盘,在VersionEdit存储新增文件信息
- 遍历Memtable,调用TableBuilder::Add把key_value写入文件
- 调用Finish
- 调用sync把缓冲区强制写入磁盘
- 生成SST文件
- 为新的SST文件挑选level,并且修改VersionEdit,添加一个文件记录,更新level层的统计信息
- 调用LogAndApply把VersionEdit更新应用到leveldb的版本库
- 调用RemoveObsoleteFiles删除废弃文件
二、SST文件合并
功能:把底层的文件合并到高层去
默认的分层size表:
l1 | l2 | l3 | l4 | l5 | l6 |
1M | 10M | 100M | 1000M | 10000M | 100000M |
L0是通过文件数量来限制的,合并发生在相邻两层之间,比如le和le+1层;首先在le层查找选中文件有key,然后去le+1选择重叠的文件,被合并的文件删除
函数功能:
-
background_compaction()
- 有Immutable Memtable,完成immu的落盘,把imm转为SST文件放入l0~l2层
- 选择要合并(PickCompaction)的level,以及le和le+1层合并的文件,结果放在compaction中
- c!=null:判断是否可以把le层文件移动到le+1层,能(31),不能(32)
- 31:选择le层文件为1,le+1层文件为0,且唯一的文件和le+2层有key范围重叠的文件总size<阈值,才为true,然后直接移走文件
- 32:正常合并,调用DoCompactionWork完成合并
- PickCompaction()
- 选择level和level层的文件:size_compaction/seek_compaction
- 选择leve+1层的文件,存在input[1]中
-
SetupOtherInputs
- 检查input_[0]中的文件input_file和level层的文件levelfile
- 检查是否能不在增加level+1层要合并的文件数量的同时增加level层选中的文件数量
-
DoCompactionWork()
- 获取最旧的仍然在被使用的快照(版本号sequece)
- 合并这些SST文件就是合并多个有序列表.MakeInputIterator对这个逻辑封装,返回的iterator
- 把Iterator指向第一个key,然后初始化些字段
- 结束当前文件,所有输出文件已完成
- 更新统计信息和版本信息
三、compaction
- Minor Compaction: 一次内存教据的特久化这程,产出是一个0层的sstable文件
- 每次compaction结束后,会生成新的sstable文件,leveldb的版本状态发生了变化,1的优先级高于2
- Major Conpactior: 将0层中的文件合并 为若干个没有数据重叠的1层文件,对不同的版本的教据项进行合并
- 触发2的条件:当0层文件数超过预定的上限(4个)、当leveli层文件的总大小超过(10^i)M、当某个文件无效读取的次数过多
整个compaction可以分为以下几步:
- 寻找合适的输入文件---->根据key的重叠情况扩大输入文件集合----->多路合并------>积分计算