参数列表
write_buffer_size
一旦memtable超过这个大小,他就会被标记为不可修改并且一个新的会被创建。默认64MB。
max_bytes_for_level_base
L1层的所有sst的最大大小。默认256MB。
db_write_buffer_size
所有column families的memtable的总的大小限制,默认是0,即不限制。
level0_file_num_compaction_trigger
见名之意,当L0的sst数量超过level0_file_num_compaction_trigger 就会着手开始compaction了。level0_file_num_compaction_trigger 默认是4。
我们可以这样估算level 0在稳定状态的大小:write_buffer_size * min_write_buffer_number_to_merge * level0_file_num_compaction_trigger。
max_write_buffer_number
内存中可以拥有刷盘到SST文件前的最大memtable数。就是是单个cl下 memtable和immetable的总数。默认是2
影响
增大 max_write_buffer_number
- 优点:允许更多的数据暂存在内存中,从而提高写入吞吐量,减少单次Flush和Compaction操作的频率。
- 缺点:内存占用增加,可能导致更高的内存压力;同时由于延迟了数据刷盘时间,可能会影响数据持久化的时间点,在系统崩溃时有丢失未刷盘数据的风险。
减小 max_write_buffer_number
- 优点:降低内存消耗,使得系统对内存的需求更为保守,数据能够更快地从内存Flushing到磁盘,降低了潜在的数据丢失风险。
- 缺点:由于MemTable数量减少,可能会导致更频繁的Flush和Compaction操作,这将影响到写入性能,并可能导致更高的磁盘I/O负载。
min_write_buffer_number_to_merge
表示最小的可以被flush的memtable的个数。默认是1。就是说只要有1个不可变的memtable,就可以向下刷到磁盘了。
举个例子,如果此参数设为2(max_write_buffer_number此时肯定大于2),那么当有至少两个不可变 memtable 时,才有可能触发 flush(亦即如果只有一个不可变 memtable,就会等待)。
在RocksDB中,min_write_buffer_number_to_merge 参数用于控制MemTable(内存表)的写入策略。当一个或多个不可变的MemTable(即Immutable MemTable)累积到满足这个参数指定的数量时,RocksDB将会触发将这些Immutable MemTable合并(Compaction)并刷入磁盘。
影响
-
控制并发度: 当增大 min_write_buffer_number_to_merge 的值时,系统会允许更多的MemTable转换为Immutable MemTable而不立即进行Flush操作,这意味着可以在内存中累积更多的数据,提高并发写入性能,尤其是在高吞吐量场景下。
-
影响空间使用: 值调大意味着可以暂时保留更多未刷到磁盘的数据在内存中,这样可能会增加内存占用,但也可能减少频繁IO带来的开销。
-
延迟和I/O负载: 调大此参数可能导致数据从内存刷到磁盘的时间点延后,进而影响到整体的持久化延迟。同时,由于一次需要合并和flush的数据量更大,可能造成短时间内更大的I/O压力。
-
读取性能: 从另一个角度看,如果数据不是立即刷到磁盘,那么后续读取请求可能需要在多个内存中的Immutable MemTable中查找,这可能会影响读取性能,特别是对于范围查询和点查询。
综上所述,调整 min_write_buffer_number_to_merge 参数是根据应用的具体需求,在内存消耗、写入性能、读取性能以及持久化延迟之间找到一个平衡点的过程。在设置时,需要综合考虑系统的资源限制、性能需求和数据安全性要求。
max_total_wal_size
wal文件的最大值。
多个column families共享一个wal,如果wal的体积超过了max_total_wal_size,就会首先新建一个wal,老的wal不再接受新数据。
等老wal涉及的column families的数据都已经下刷到sst了,就说明这个老的wal不用了,系统就会删除它。
默认情况下max_total_wal_size是0,系统会使用多个columnFamily的write_buffer_size* max_write_buffer_number的积相加。(write_buffer_size* max_write_buffer_number就是一个column family在内存中的数据总量)
max_background_jobs
compaction和flush的后台线程数之和。默认是2。
max_background_compactions
compaction的线程数,默认是-1,统一由系统管理。
max_background_flushes
flushs的线程数,默认是-1,统一由系统管理。
target_file_size_base 与 target_file_size_multiplier
target_file_size_multiplier 默认是1
target_file_size_base L1层每个sst文件的大小,默认64MB。
L2层每个sst文件的大小等于target_file_size_base *target_file_size_multiplier
L2层每个sst文件的大小等于target_file_size_base *target_file_size_multiplier *target_file_size_multiplier
也就是说如果target_file_size_multiplier 是10,那么L2层每个sst文件大大小就是640MB,L3层的每个文件大小就是6400MB。
但是默认情况下target_file_size_multiplier 是1,也就是说所有层的每个sst文件大小就是64MB
关于write stall
先说当系统的flush或者compaction太慢的时候,就会出现memtable太多,或者L0文件太多,或者待compaction的文件过多的情况。
用户的读流程是先读memtable,再度immemtable然后依次读L0的各个sst文件。
如果memtable太多,或者L0文件太多那势必会造成读延迟增大。
所以一旦出现memtable太多,或者L0文件太多的情况,rocksdb就会降低写请求甚至暂停写请求来停止memtable的继续扩张。
具体来说
memtable太多
- 延缓写: 如果max_write_buffer_number 大于3, 将要flush的memtables(immemtable)大于等于max_write_buffer_number - 1, write 就会延缓
- 停写: 如果将要flush 的memtable的个数大于等于max_write_buffer_number, write 直接停止等flush完成
以咱们默认的参数来看,max_write_buffer_number为2,也就是说,最多有一个immemtable和一个memtable。然后memtable写满了,但是之前的immemtable还没有下刷,那么写请求就会停止。
一旦出现延缓写或者彻底停写,就出出现下面的日志:
假定max_write_buffer_number 设置的是5
Stopping writes because we have 5 immutable memtables (waiting for flush), max_write_buffer_number is set to 5
Stalling writes because we have 4 immutable memtables (waiting for flush), max_write_buffer_number is set to 5
L0层文件太多
- 延缓写: 如果L0的文件数量达到了level0_slowdown_writes_trigger(默认20),write 延缓写
- 停写: 如果文件数量达到了level0_stop_writes_trigger(36), 直接停写直到L0->L1的compactiom减少了L0的文件数。
以上两种情况时, 会出现这样的日志
Stalling writes because we have 4 level-0 files
Stopping writes because we have 20 level-0 files
大家请注意level0_file_num_compaction_trigger 默认值是4。
待caompaction的文件太多
- 延缓写: 如果要compation的的字节数达到soft_pending_compaction_bytes_limit(64GB),延缓写
- 停写: 如果该字节数目大于hard_pending_compaction_bytes_limit(256GB), 直接停写
相应的日志
Stalling writes because of estimated pending compaction bytes 500000000
Stopping writes because of estimated pending compaction bytes 1000000000
write stall的处理
首先如果在日志里发现了上面的异常日志,先确定是因为什么导致的write stall
memtable太多
- 增大max_write_buffer_number 让每个cf里面可以使用更多的memtable
L0文件太多
- 增大 level0_slowdown_writes_trigger
待compaction的文件体积太大
- 同时增加max_background_jobs和max_background_compactions
参考资料
http://rocksdb.org.cn/doc/Write-Stalls.html