SStable是一种不可变的、排序的、持久化的key_value Map, LSM-Tree是一种能够将批量随机写,转换为顺序写的数据结构,其实本质就是不断产生SSTree结构的Log文件,然后不断Merge以提高文件效率的,它是一种分层的组织数据的结构,具体到实现上就是一些按照逻辑分层的有序文件一言概述的话 :LSM-Tree的树节点可以分为两种,保存在内存中的称之为MemTable, 保存在磁盘上的称之为SSTable
- 一个db一个目录,目录下有sstables子目录,用来存放sstable,还有一个log目录,用来存放wal log,创建这些子目录的时候需要做sync,确保创建成功。
- sstable目录下每一个文件都是一个sstable,文件名就是sstable的id的十六进制表示,sstable id是一个始终递增的u64
- 一个sstable的layout是crc + tombstone discriminant + key + value,4个字节的crc校验,一个字节用来表示当前的这个key/value的状态是新增还是删除,接下来就是固定size大小的key和value了。如果这条记录是表示删除某个key,那value部分可以为空,但是仍然会写zero进去,在整个sstable的最开始还有8个字节记录了整个sstable中记录的key/value个数。
- log目录下存的是wal log,其layout是header(5个字节) + tuple(最小8个字节,最大key和value的大小相加)
- 插入数据的时候,需要先将数据写入到wal log中,写入的时候需要根据key/value计算crc,然后先写crc内容,然后写标记位,标记是删除还是插入,然后写key和value的数据。这样就完成了一条entry的写入,接着会将数据写入到memtable(就是内存的中map)中。最后将数据插入到内存中的map数据结构。
- 删除数据实际就是插入一个value为None的条目,流程和插入一样
- flush数据其实上分了几步,第一个就是flush log文件,确保记录的数据落盘,然后看下当前内存的未Flush的数据是否超过阀值,超过了就开始将memtable持久化到一个新的sstable中。写sstable的时候,先写临时文件,然后原子的rename过去。接着触发后台任务进行sstable的compact,最后reset掉wal log文件。
- 后台任务进行compact的时候,会统计所有的sstable占用的磁盘大小,以及当前所有key/value存储在内存中的大小,两者之差大于某个阀值就进行compact,或者sstable的数量大于配置的合并windows数量。这个时候就将sstable按照windows分组切割,对于每一个windows如果符合条件就进行compact
- compact本质上就是将一对sstable文件恢复到内存中,形成一个新的更大的ssbale,然后移除老的sstable文件。
- batch写入的时候,会写入一条batch记录,batch记录本身和一个key/value记录大小都是一样的,只是它的key是batch size,value是填充的0,他的crc是batch size计算出来的,他的 tombstone discriminant 位置存放的是2。除此之外和正常的key/value entry一模一样,batch的时候,先写入batch entry,然后遍历每一个key/value按照正常的流程插入即可。