本文缺少實際的實踐經驗。全部來自在網上的“道聽途說”和自己的“胡思亂想”。
寫放大、讀放大、空間放大
基于 LSM-Tree 的存儲系統越來越常見了,如 RocksDB、LevelDB。LSM-Tree 能将離散的随機寫請求都轉換成批量的順序寫請求(WAL + Compaction),以此提高寫性能。但也帶來了一些問題:
- 讀放大(Read Amplification)。LSM-Tree 的讀操作需要從新到舊(從上到下)一層一層查找,直到找到想要的資料。這個過程可能需要不止一次 I/O。特别是 range query 的情況,影響很明顯。
- 空間放大(Space Amplification)。因為所有的寫入都是順序寫(append-only)的,不是 in-place update ,是以過期資料不會馬上被清理掉。
RocksDB 和 LevelDB 通過背景的 compaction 來減少讀放大(減少 SST 檔案數量)和空間放大(清理過期資料),但也是以帶來了寫放大(Write Amplification)的問題。
- 寫放大。實際寫入 HDD/SSD 的資料大小和程式要求寫入資料大小之比。正常情況下,HDD/SSD 觀察到的寫入資料多于上層程式寫入的資料。
在 HDD 作為主流存儲的時代,RocksDB 的 compaction 帶來的寫放大問題并沒有非常明顯。這是因為:
- HDD 順序讀寫性能遠遠優于随機讀寫性能,足以抵消寫放大帶來的開銷。
- HDD 的寫入量基本不影響其使用壽命。
現在 SSD 逐漸成為主流存儲,compaction 帶來的寫放大問題顯得越來越嚴重:
- SSD 順序讀寫性能比随機讀寫性能好一些,但是差距并沒有 HDD 那麼大。是以,順序寫相比随機寫帶來的好處,能不能抵消寫放大帶來的開銷,這是個問題。
- SSD 的使用壽命和其寫入量有關,寫放大太嚴重會大大縮短 SSD 的使用壽命。因為 SSD 不支援覆寫寫,必須先擦除(erase)再寫入。而每個 SSD block(block 是 SSD 擦除操作的基本機關) 的平均擦除次數是有限的。
是以,在 SSD 上,LSM-Tree 的寫放大是一個非常值得關注的問題。而寫放大、讀放大、空間放大,三者就像 CAP 定理一樣,需要做好權衡和取舍。
RockDB 寫放大簡單分析
說明:RocksDB 支援多種 Compaction。下面分析的是 Level Style Compaction。
RocksDB 的寫放大分析:
- +1 - redo log 的寫入
- +1 - Immutable Memtable 寫入到 L0 檔案
- +2 - L0 和 L1 compaction(L0 SST 檔案的 key 範圍是重疊的,出于性能考慮,一般盡量保持 L0 和 L1 的資料大小是一樣的,每次拿全量 L0 的資料和全量 L1 的資料進行 compaction)
- +11 - Ln-1 和 Ln 合并的寫入(n >= 2,預設情況下,Ln 的資料大小是 Ln-1 的 10 倍,見 max_bytes_for_level_multiplier )。
是以,總的寫放大是 4 + 11 * (n-1) = 11 * n - 7 倍。關鍵是 n 的取值。
假設 max_bytes_for_level_multiplier 取預設值 10,則 n 的取值受 L1 的大小和 LSM-Tree 的大小影響。 L1 的大小由 max_bytes_for_level_base 決定,預設是 256 MB。
預設情況下 L0 的大小和 L1 一樣大,也是 256 MB。不過 L0 比較特殊,當 L0 的 SST 檔案數量達到 level0_file_num_compaction_trigger 時,觸發 L0 -> L1 的 comapction。是以 L0 的最大大小為
write_buffer_size * min_write_buffer_number_to_merge * level0_file_num_compaction_trigger
。
- write_buffer_size 預設 64 MB。
- min_write_buffer_number_to_merge 預設 1。
- level0_file_num_compaction_trigger 預設 4。 是以 L0 預設最大為 64 MB * 1 * 4 = 256 MB。
是以,RocksDB 每一層的預設大小為 : L0 - 256 MB L1 - 256 MB L2 - 2.5 GB L3 - 25 GB L4 - 250 GB L5 - 2500 GB
使用者可以根據自己的場景需求調整上面的各個參數。
leveldb的讀寫放大簡單分析

參考文檔
- RocksDB Tuning Guide
- RocksDB 源碼
本文參與騰訊雲自媒體分享計劃,歡迎正在閱讀的你也加入,一起分享。