【翻譯】rocksdb write stall

2023-06-27 12:01:00

翻譯自官方wiki:https://github.com/facebook/rocksdb/wiki/Write-Stalls
轉載請註明出處:https://www.cnblogs.com/morningli/p/16791706.html


write stall

當flush或compaction無法跟上寫入的速率時,rocksdb有旁路系統來減慢寫入速率。如果沒有這樣的系統,使用者如果持續寫入比硬體能處理的資料,資料庫會發生下面的問題:

  • 增加空間放大,會導致磁碟空間用光
  • 增加讀放大,嚴重損害讀效能

這個想法是將寫入減慢到資料庫可以處理的速度。然而,有時候資料庫會對臨時的突發寫過於敏感,或者低估了硬體的處理能力,所以你可能會看到預料外的慢或者查詢超時。

為了找出你的資料庫是否有write stall的問題,你可以檢查:

  • LOG檔案,當write stall發生時會包含info紀錄檔
  • 在LOG檔案中找到 Compaction stats

write stall的原因

可能會因以下原因觸發stall:

  • 太多memtable。當等待flush的memtable的數量大於或者等於max_write_buffer_number,寫入會完全停止寫來等待flush結束。另外如果max_write_buffer_number 大於3,等待flush的memtable大於或等於max_write_buffer_number-1,寫入則會stall。在這些情況下,你將在 LOG 檔案中獲得類似於以下內容的info紀錄檔:

    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

  • 太多0層sst檔案。 當0層的sst檔案數量達到level0_slowdown_writes_trigger, 寫入則會stall。當0層的sst檔案數量達到level0_stop_writes_trigger,寫入會完全停止,等待0層到1層的compaction減少0層的檔案數。在這些情況下,你將在 LOG 檔案中獲得類似於以下內容的info紀錄檔:

    Stalling writes because we have 4 level-0 files

    Stopping writes because we have 20 level-0 files

  • 太多等待compaction的位元組數。 當估計等待compaction的位元組數達到soft_pending_compaction_bytes,寫入則會stall。當評估等待的位元組數達到hard_pending_compaction_bytes,寫入會完全停止等待compaction。在這些情況下,你將在 LOG 檔案中獲得類似於以下內容的info紀錄檔:

    Stalling writes because of estimated pending compaction bytes 500000000

    Stopping writes because of estimated pending compaction bytes 1000000000

每當stall條件被觸發,rocksdb會減少寫速度到delayed_write_rate,如果等待compaction的位元組還在增加,也有可能會減少到比delayed_write_rate更低。值得注意的一鍵式是減慢/停止的觸發和等待compaction的位元組數限制是每個column family單獨設定的,但是write stall 是應用到整個資料庫的,這意味著如果一個column family觸發write stall,整個資料庫都會被stall。

非阻塞寫

如果觸發了一個寫減慢/停止,執行Put/Merge/Delete等的程式執行緒會被阻塞。如果一個減慢在生效中,每個寫在處理之前會睡眠一段時間(一般是1ms)。如果寫是stall的,執行緒可以無限制地阻塞。如果不希望執行緒被阻塞,應用可以通過在WriteOptions中設定no_slowdown = true來避免。在這個選項下,如果寫請求因為減慢/stall導致沒有完成,會立馬返回Status::Incomplete()。

在內部,為了增加效能,rocksdb在寫到WAL之前會嘗試將來自不同執行緒的寫入請求批次處理在一起。然而設定了no_slowdown 的寫請求不會這樣做,這可能會導致輕微的效能損失。

減輕 write stall

有很多選項你可以調整來減輕write stall。如果你有一些負載可以接受write stall,有些不能,你可以設定一些寫請求為 Low Priority Write 來避免延遲敏感的寫請求被stall。

如果write stall是由待處理的flush引起的,你可以嘗試:

  • 增加 max_background_jobs 使用更多的flush執行緒
  • 增加 max_write_buffer_number 減少flush的memtable大小(這裡是不是寫錯了??)

如果write stall是由太多0層檔案或者太多等待compaction的位元組數引起的,compaction跟不上寫入的速度。請注意,任何減少寫放大的操作都會減少compaction需要寫入的位元組數,從而加快壓縮速度。嘗試的選項:

  • 增加 max_background_jobs 使用更多的compaction執行緒
  • 增加write_buffer_size擁有更大的memable,減少寫放大
  • 增加min_write_buffer_number_to_merge

你可以設定停止/減慢觸發器和待compacrion位元組數限制為一個很大的數位來避免發生write stall。如果你正在批次匯入資料到rocksdb也可以看一下在 FAQ 中的「What's the fastest way to load data into RocksDB?」。

寫緩衝區管理器stall

WriteBufferManager 提供一個了選項allow_stall可以傳遞給WriteBufferManager的建構函式。如果設定為true,當記憶體使用超過buffer_size (軟限制)時會stall所有寫入。它將等待重新整理完成並且記憶體使用量下降。應用可以通過在設定WriteOptions中設定no_slowdown = true來避免。