RocksDB 源码分析 – WAL
WAL
RocksDB 的 WAL 格式和 LevelDB 相同,划分为固定大小的 block,用 crc32c 校验。写 WAL 时会禁用 mmap() 和 direct I/O,见 env_posix.cc:OptimizeForLogWrite(),看来是性能不好或者效果不明显。
WAL 还会设置 write time life hint:fcntl(fd, F_SET_RW_HINT, RWH_WRITE_LIFE_SHORT),具体作用不太清楚,man page 描述也很模糊。也会用 fallocate() 预先分配空间,preallocation block size 是根据 write buffer size、max_total_wal_size 等配置计算的。
刷盘
WAL 的刷盘策略可配:
- 设置
WriteOptions::sync,写完后立刻刷盘。 - 设置
DBOptions::wal_bytes_per_sync,每写一定数据会刷盘。 - 最后是由操作系统来刷盘。
manual_wal_flush
WAL 是用 WritableFileWriter 写的,内部会用 AlignedBuffer 缓冲数据,只有当 buffer 满了或者主动 flush、sync 时才会真正写文件,buffer 的最大大小由 DBOptions::writable_file_max_buffer_size 配置。
一般情况下每次都会 flush,但可以配置 DBOptions::manual_wal_flush,主动调 flushWAL() 或者 buffer 满了时才写文件,在某些场景下可提高性能,如 MyRocks 的 2pc,见 FlushWAL; less fwrite, faster writes。
TODO
几个问题先留着,等后面看到时再补充:
WAL切换:LevelDB是memtable满了后,切到新的memtable + WAL,而RocksDB有column family,当flush时,会切到新的WAL;当WAL大小超过DBOptions::max_total_wal_size也会切换。WAL清理:LevelDB当memtable compaction完成,WAL可以删。RocksDB不是立即删除的,而是先archive,根据配置DBOptions::WAL_ttl_seconds, DBOptions::WAL_size_limit_MB清理,好像是为了replication。- 复用之前的
WAL,见DBOptions::recycle_log_file_num。 - 最近好像才实现写失败的
recovery,见db/error_handler。
留下评论