WAL
参考资料:
- https://gocode.cc/project/13/...
- https://iggiewang.cn/2021/04/...
- http://mysql.taobao.org/month...
- https://github.com/facebook/r...
在RocksDB中,WAL的写入是单线程顺序串行写入的,而MemTable则是可以并发多线程写入的(通过allow_concurrent_memtable_write
配置打开),或许在系统压力到一定阶段的时候, 写入WAL会成为性能的瓶颈。
多个写线程会组合成一个链表形式的write_group,而第一个进入链表的会成为leader,其他为follower。
创建完成该链表之后,则开始计算有多少个写请求可以批量的进行,同时更新写请求组write_group中的批量写尺寸以及个数等信息。该操作完成之后,则将进入写WAL的流程,根据write_group生成一个merged_batch,该merged_batch中记录着应当被写入WAL的内容。接着就通过WriteToWAL将merged_batch写入WAL中,这里会根据WriteOptions.sync
配置来决定是否对WAL进行落盘操作。
如果WriteOptions.sync
为false,WAL不会被同步进硬盘。除非操作系统认为这些数据必须被flush(例如产生了太多的dirty pages),用户不需要等待任何写入IO。这种模式下,WAL的写不是crash safe的。
在WAL的写入完成后,leader会唤醒follower,并行地(可配置)向Memtable写入。当Immutable Memtable被flush或是WAL的文件大小达到max_total_wal_size
(默认为Memtable大小的四倍)时,新的WAL会被创建出来。而后者的创建也会和Memtable的flush一块进行。
如果开启enable_pipelined_write
配置,将引入流水线,第一个group的WAL提交后,在它执行memtable写入时,下一个group同时开启,以到达Pipeline写入的效果。
Manifest
参考:
https://gocode.cc/project/13/...
在rocksdb中,为了恢复磁盘上数据的一致性状态,引入了Version概念,通过记录每一次的Version变更,形成MANIFEST日志。
每次Immutable memtable落盘后,就会修改一次磁盘的SST文件列表,这时候会产生一次VersionEdit同时通过此VersionEdit来生成一个新版本。该VersionEdit会写入到一个日志中,该日志存储着最近的所有VersionEdit,该文件就被称之为Manifest log。当一个Manifest log被写满之后,则会生成一个新的Manifest log。
在生成了新文件并且写入完毕之后,在CURRENT文件中的内容更改为最新的Manifest log文件名。
当一个操作通过迭代器迭代数据的时候,会引用当前最新的Version,该Version会存在于VersionSet中,即使经过了Compact后该文件被移除了,亦或者是新增了新的SST后产生了新的Version,都不会影响当前迭代器所可见的数据范围。当迭代器迭代结束之后,则会解除对该Version引用。当一个Version没有被引用且不是最新的版本时,则可以被移除,同时对其包含的所有SST解除引用。相似的,当某个SST文件没有被任何的Version引用的时候,也会被清理。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。