https://leveldb-handbook.readthedocs.io/zh/latest/basic.html
https://github.com/google/leveldb/blob/main/doc/impl.md
leveldb架构

leveldb写流程概述
- 将所有的写操作写到日志文件(log文件)中
- 将内容写入到内存中
- 先memtable,等到其存储内容的容量达到阈值时(默认为4MB),便将其转换成一个不可修改的memtable,与此同时创建一个新的memtable,供用户继续进行读写操作。
- 当一个immutable memtable被创建时,leveldb的后台压缩进程便会将利用其中的内容,创建一个sstable,持久化到磁盘文件中。
- memtable
- 其中数据按用户定义的排序方法排序之后按序存储
- 跳表实现,这种数据结构绝大多数操作的时间复杂度为O(log n)
- immutable memtable和memtable的结构定义完全一样
- 写入磁盘
- compaction
虽然每个memetable中所有的数据都是按序排列的,但是当多个memetable数据持久化到磁盘后,对应的不同的sstable之间是存在交集的(比如两个table中都出现了某条kv pair),在读操作时,需要对所有的sstable文件进行遍历,严重影响了读取效率。因此leveldb后台会“定期“整合这些sstable文件,该过程也称为compaction。
- 随着compaction的进行,sstable文件在逻辑上被分成若干层,由内存数据直接dump出来的文件称为
level 0
层文件,后期整合而成的文件为level i
层文件
- compaction
manifest
版本
版本定义
- 一个版本中主要记录了
- 每一层中所有文件的元数据,元数据包括(1)文件大小(2)最大key值(3)最小key值。
- 一些进行compaction的统计值,来控制compaction的进行
- 元数据结构举例(goleveldb,类型在名后面)
// tFile holds basic information about a table. type tFile struct { fd storage.FileDesc seekLeft int32 size int64 imin, imax internalKey }
- 版本结构举例
type version struct { s *session // session - version levels []tFiles // file meta 每层文件的元数据 // 压缩信息 // Level that should be compacted next and its compaction score. // Score < 1 means compaction is not strictly needed. These fields // are initialized by computeCompaction() cLevel int // next level cScore float64 // current score cSeek unsafe.Pointer closing bool ref int released bool }
创建版本
当每次compaction完成(或者换一种更容易理解的说法,当每次sstable文件有新增或者减少),leveldb都会创建一个新的version
manifest文件记录版本更新(versionEdit)
- 每次leveldb启动时,都会创建一个新的Manifest文件
- 下图是一个manifest文件的示意图,其中包含了3条versionEdit记录,每条记录包括(1)新增哪些sst文件(2)删除哪些sst文件(3)当前compaction的下标(4)日志文件编号(5)操作seqNumber等信息。
- 通过这些信息,leveldb便可以在启动时,基于一个空的version,不断apply这些记录,最终得到一个上次运行结束时的版本信息。
current
记载当前的manifest文件名
*.log
log files(WAL)
LOG and LOG.old
Informational messages are printed to files named LOG and LOG.old