RocksDB 使用 LSM 的方式用來提升寫入的性能,但如果寫入過快察滑,超過了 RocksDB 處理的極限打厘,RocksDB 就會考慮對寫入進(jìn)行降速處理。這個在 TiKV 調(diào)優(yōu)的時候遇到過很多次贺辰,當(dāng)我們持續(xù)大量插入數(shù)據(jù)的時候户盯,會發(fā)現(xiàn)到了某一個時間,性能就突然下降了饲化,如果突然出現(xiàn)了這樣的情況莽鸭,我們都會從 LOG 文件里或者 statistics 上面來確認(rèn)是否出現(xiàn)了 write stall。
Where Stall
通常 write stall 會在幾個地方出現(xiàn)
Too many memtables
當(dāng)需要等待被 flush 到 level 0 的 memtable 到了或者超過了 max_write_buffer_number
滓侍,RocksDB 就會完全 stop 寫入蒋川,直到 flush 結(jié)束。同時撩笆,當(dāng) max_write_buffer_number
大于等于 3捺球,需要 flush 的 memtable 數(shù)量已經(jīng)大于等于 max_writer_buffer_number - 1
的時候,RocksDB 就會 stall 寫入夕冲。我們可以在 LOG 里面看到如下的信息:
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
Too many level-0 SST files
當(dāng) level 0 的 SST file 的數(shù)量達(dá)到 level0_slowdown_writes_tigger
的時候氮兵,RocksDB 就會 stall 寫入。當(dāng) level 0 的 SST file 的數(shù)量達(dá)到 level0_stop_writes_trigger
的時候歹鱼,RocksDB 就會 stop 寫入泣栈,直到 level 0 到 level 1 之間的 compaction 完成,level 0 SST file 的數(shù)量減少之后弥姻。我們可以在 LOG 里面看到如下的信息:
Stalling writes because we have 4 level-0 files
Stopping writes because we have 20 level-0 files
Too many pending compaction bytes
當(dāng)預(yù)計的 compaction 數(shù)據(jù)的大小達(dá)到了 sofe_pending_compaction_bytes
之后南片,RocksDB 會 stall 寫入。當(dāng)達(dá)到了 hard_pending_compaction_bytes
之后庭敦,則會 stop 寫入疼进。我們可以在 LOG 里面看到如下的信息:
Stalling writes because of estimated pending compaction bytes 500000000
Stopping writes because of estimated pending compaction bytes 1000000000
Mitigate Stall
需要注意的是,很多時候秧廉,受限于機(jī)器的性能伞广,我們并不能杜絕 stall拣帽,只能通過配置盡量的改善。
當(dāng)發(fā)生 stall 的時候嚼锄,RocksDB 會降低寫入的速度到 delayed_write_rate
减拭,甚至有可能比這個更低。另外需要注意的是 slowdown/stop trigger 或者 pending compaction limit 都是針對不同的 CF 的区丑,但 stall 是針對整個 DB 的拧粪,如果程序里面有多個 CF,一個 CF 出現(xiàn)了 stall 的情況刊苍,整個 DB 都會 stall既们。
如果 stall 是因為 pending flush memtable 不及時導(dǎo)致的濒析,我們可以嘗試:
- 增大
max_background_flushes
正什,這樣就能有更多的線程同時 flush memtable。 - 增大
max_write_buffer_number
号杏,用更小的 memtable 來提升 flush 的速度婴氮。
如果 stall 是因為 level 0 或者 pending compaction 太多導(dǎo)致,我們就需要考慮提升 compaction 的速度盾致。另外主经,也可以減小寫放大,因為寫放大越小庭惜,需要 compaction 的數(shù)據(jù)量就越小罩驻。所以我們可以嘗試:
- 增大
max_background_compactions
,用更多的線程來進(jìn)行 compaction护赊。 - 增大
write_buffer_size
惠遏,這樣就能有更大的 memtable,用來減少寫放大 - 增加
min_write_buffer_number_to_merge
骏啰,在 flush 之前先將 memtable merge节吮,減少寫入 key 的數(shù)量,但這樣會影響從 memtable read 的性能判耕。
小結(jié)
對于寫性能要求非常高的系統(tǒng)來說透绩,write stall 是一個繞不過去的坎,所以我們只能在不同的場景下面通過配置來在 write壁熄,read 和 space 這三個上面做平衡帚豪。所以需要更加深入的去理解 RocksDB 那一坨參數(shù)以及相關(guān)的含義。