Tuning RocksDB - Write Stalls

RocksDB 使用 LSM 的方式用來提升寫入的性能,但如果寫入過快,超過了 RocksDB 處理的極限,RocksDB 就會考慮對寫入進行降速處理。這個在 TiKV 調優的時候遇到過很多次,當我們持續大量插入數據的時候,會發現到了某一個時間,性能就突然下降了,如果突然出現了這樣的情況,我們都會從 LOG 文件里或者 statistics 上面來確認是否出現了 write stall。

Where Stall

通常 write stall 會在幾個地方出現

Too many memtables

當需要等待被 flush 到 level 0 的 memtable 到了或者超過了 max_write_buffer_number,RocksDB 就會完全 stop 寫入,直到 flush 結束。同時,當 max_write_buffer_number 大于等于 3,需要 flush 的 memtable 數量已經大于等于 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

當 level 0 的 SST file 的數量達到 level0_slowdown_writes_tigger 的時候,RocksDB 就會 stall 寫入。當 level 0 的 SST file 的數量達到 level0_stop_writes_trigger 的時候,RocksDB 就會 stop 寫入,直到 level 0 到 level 1 之間的 compaction 完成,level 0 SST file 的數量減少之后。我們可以在 LOG 里面看到如下的信息:

Stalling writes because we have 4 level-0 files

Stopping writes because we have 20 level-0 files

Too many pending compaction bytes

當預計的 compaction 數據的大小達到了 sofe_pending_compaction_bytes 之后,RocksDB 會 stall 寫入。當達到了 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

需要注意的是,很多時候,受限于機器的性能,我們并不能杜絕 stall,只能通過配置盡量的改善。

當發生 stall 的時候,RocksDB 會降低寫入的速度到 delayed_write_rate,甚至有可能比這個更低。另外需要注意的是 slowdown/stop trigger 或者 pending compaction limit 都是針對不同的 CF 的,但 stall 是針對整個 DB 的,如果程序里面有多個 CF,一個 CF 出現了 stall 的情況,整個 DB 都會 stall。

如果 stall 是因為 pending flush memtable 不及時導致的,我們可以嘗試:

  • 增大 max_background_flushes ,這樣就能有更多的線程同時 flush memtable。
  • 增大 max_write_buffer_number ,用更小的 memtable 來提升 flush 的速度。

如果 stall 是因為 level 0 或者 pending compaction 太多導致,我們就需要考慮提升 compaction 的速度。另外,也可以減小寫放大,因為寫放大越小,需要 compaction 的數據量就越小。所以我們可以嘗試:

  • 增大 max_background_compactions,用更多的線程來進行 compaction。
  • 增大 write_buffer_size,這樣就能有更大的 memtable,用來減少寫放大
  • 增加 min_write_buffer_number_to_merge,在 flush 之前先將 memtable merge,減少寫入 key 的數量,但這樣會影響從 memtable read 的性能。

小結

對于寫性能要求非常高的系統來說,write stall 是一個繞不過去的坎,所以我們只能在不同的場景下面通過配置來在 write,read 和 space 這三個上面做平衡。所以需要更加深入的去理解 RocksDB 那一坨參數以及相關的含義。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容