# RocksDB: 写入 (继续...)

__*Level*__
__*compaction*__

![left](./student-guide/diagram/RocksDBWrite02_aa_001_20220511.png)
-------------------------------------------------------------
下面,我们着重讨论下 RocksDB 的数据落盘后的文件组织方式。

磁盘上的文件被分成多层进行组织。我们叫它们为 Level-1,Level-2 ... 等等,或者简单的 L1 , L2 ... 等等。一个特殊的层,Level-0 ( L0 ),会包含刚从内存 MemTable 落盘的数据,到达 4 个会触发 compaction 向下一层,如果积压达到 20 个,会触发 write stall。每个层（除了 Level0 ）都是一个独立的排序结果。

在每一层（除了Level-0）,数据被切分成多个SST文件。

每个 SST 文件中的 key 都是排好序的。如果需要定位一个 key ,我们先二分查找所有文件的起始和结束 key,定位哪个文件有这个 key ,然后二分查找具体的文件,来定位 key 的位置。总的来说,就是在该层的所有key里面进行二分查找。

所有非  0 层都有目标大小。压缩的目标是限制这些层的数据大小,大小目标通常是指数增加。

最后,关于 WAL 的日志,WAL 会把 MemTable 的操作序列化之后以日志文件形式存储在持久化介质中。发生崩溃的时候,WAL 日志（ log ）文件可以用于重新构建 MemTable,帮助数据库恢复数据库到一个一致的状态。当一个 MemTable 被安全地落盘到持久化介质之后,相关的 WAL 日志（ log ）会变成过期的,然后被归档。最终归档的日志会在一定时间后被从硬盘上删除。

到此为止,数据就被持久化写入了,我们可以看到,WAL 一开始就保证了写不丢失,接下来我们总结一下 RocksDB 的 CRUD 大致流程:

写入操作
写操作首先需要通过 WAL 将数据写入到磁盘日志（ Log ）中,防止数据丢失,然后数据会被写入到内存的 MemTable 中,这样一次写操作已经完成了,只需要 1 次磁盘 IO,再加 1 次内存操作。相较于 B+ 树的多次磁盘随机 IO,大大提高了效率。随后,这些在 MemTable 中的数据会被批量地合并到磁盘中的 SSTable 当中,将随机写变为了顺序写。

删除操作
当有删除操作时,并不需要像 B+ 树一样,在磁盘中找到相应的数据后再删除,只需要在 MemTable 中插入一条数据当作标志,如 delete key:1233 ,当读操作读到 MemTable 中的这个标志时,就会知道这个 key 已被删除。随后在日志合并中,这条被删除的数据会在合并的过程中一起被删除。

更新操作
更新操作和删除操作类似,都是只操作 MemTable,写入一个标志,随后真正的更新操作被延迟在合并时一并完成。

















