摘要: Google LevelDB 锁服务
无论是 put 、 delete 还是batch操作,leveldb 底层都是以 batch 作为执行实例。
// Batch is a write batch.
type Batch struct {
data []byte
index []batchIndex
// internalLen is sums of key/value pair length plus 8-bytes internal key.
internalLen int
}
leveldb的写入是类似线程组的模式,各个线程会将任务其放入队列中,拿到锁的线程会批量取任务然后合并后写入。
读取流程比较简单,按照 Memtable –> Immutable –> sstable(level0~7)
对于文件的读取,每次读取会减少其 score,具体作用可以看 Major Compaction 的过程四。
内存的持久化在 leveldb 称为 Minor Compaction ,每次 minor compaction 都会产出一个 level 0层的 sstable,多个文件中可能会存在数据 overlap。
因为 minor compaction 必须要在短时间完成(阻塞写入操作),因此其优先级要比 Major Compaction 更高,在进行 minor compaction 时会暂停 Major Compaction
overlap,因为内存的 memtable 是按照阈值分割的,所以可能出现一个数据存在多个文件中
随着 level 0层的 sstable 越来越多,导致查询越来越慢,leveldb 会将 level 0层的文件进行归并到 level 1层,这个操作称为 Major Compaction 。
当用户写入的速度始终大于 Major Compaction 时,会导致 level 0层的文件数量越来越多,读取性能持续拉胯,leveldb 为此设计了一种平衡策略:
Major Compaction 触发条件:
采用轮换的方法选择文件,第一批选完会记录其最大key,下一次从这个key后的文件开始,如下图中选中了黄色区域。
在当前层继续寻找与过程一原始输入文件有重叠的文件,如下图中选中了蓝色区域。
将选中的文件集合,进行冗余清理、归并排序到原始输入文件的下一个level (如下图是归并到 level 1中的红色区域)。
根据得分来选择合并的 level
为每个新的 sstable 文件维护初始分数为 100,每查一次该文件就减一,递减到0会被标记为待合并。