聊聊RocksDB Compact
導(dǎo)語(yǔ)?對(duì)于 LevelCompact 策略,RocksDB會(huì)根據(jù)每一層不同的策略計(jì)算出CompactScore,根據(jù)CompactScore大小來(lái)決定那一層將會(huì)優(yōu)先進(jìn)行Compact,然后選擇Level-N 和Level-(N+1)的文件進(jìn)行Compact。如何計(jì)算CompactScore? 如何選擇文件進(jìn)行Compact?Compact有哪些參數(shù)?如何知道RocksDB當(dāng)前的一個(gè)狀態(tài)?
?
RocksDB是基于LSM結(jié)構(gòu)的K-V存儲(chǔ)引擎,由于數(shù)據(jù)文件采用Append Only方式寫(xiě)入,而對(duì)于過(guò)期的數(shù)據(jù)、重復(fù)的數(shù)據(jù)必然會(huì)存在有多份副本,這部分?jǐn)?shù)據(jù)通過(guò)Compact的方式進(jìn)行逐步的清理。?
那么這里好奇的提出幾個(gè)問(wèn)題,由這幾個(gè)問(wèn)題引出下文:
由于我們的TRedis底層采用RocksDB存儲(chǔ)引擎進(jìn)行持久化,底層數(shù)據(jù)文件采用分層的方式管理,故這里討論的Compact 基于Level Compact 。
數(shù)據(jù)怎么來(lái)?我們調(diào)用TRedis接口進(jìn)行寫(xiě)數(shù)據(jù)時(shí),數(shù)據(jù)會(huì)先寫(xiě)入到內(nèi)存中的Memtable里邊,當(dāng)Memtable寫(xiě)滿(mǎn)后會(huì)寫(xiě)入下一個(gè)Memtable,Memtable采用Skiplist結(jié)構(gòu)以此保證數(shù)據(jù)按照Key的字典序進(jìn)行排序,同時(shí)這個(gè)Memtable會(huì)被后臺(tái)線程刷到磁盤(pán)文件–Level-0,當(dāng)Level-0文件個(gè)數(shù)達(dá)到一定數(shù)量,Compact線程可能會(huì)進(jìn)行Compact,由此產(chǎn)生Level-1,當(dāng)Level-1文件總大小達(dá)到一定大小后, Compact線程可能會(huì)進(jìn)行Compact,由此產(chǎn)生Level-2,…….
RocksDB對(duì)每一層的處理規(guī)則不太一樣,由于Level-0層的數(shù)據(jù)直接由Memtable dump得到,從而不能保證Level-0層的每個(gè)文件Key的范圍不能有交集,故對(duì)Level-0層的會(huì)進(jìn)行特殊處理,而對(duì)于Level-1+層處理規(guī)則一樣。
Level-0 層的文件在不停的從Memtable 中dump出來(lái),那么何時(shí)才會(huì)把這些Level-0層的文件合并到Level-1 ??
RocksDB對(duì)對(duì)每一層進(jìn)行打分,分?jǐn)?shù)從0~1000000,這個(gè)分?jǐn)?shù)的大小決定了進(jìn)行Compact 的優(yōu)先級(jí),分?jǐn)?shù)越大,越先進(jìn)行Compact。
那么這個(gè)分?jǐn)?shù)如何計(jì)算出來(lái)?
- 如果是Level-0層,會(huì)先算出當(dāng)前有多少個(gè)沒(méi)有進(jìn)行Compact 的文件個(gè)數(shù)numfiles, 然后根據(jù)這個(gè)文件的個(gè)數(shù)進(jìn)行判斷,當(dāng)numfiles<20 時(shí),Score = numfiles/4;當(dāng)24>numfiles>=20時(shí),Score = 10000;當(dāng) numfiles>=24時(shí),Score = 1000000:
| level0_file_num_compaction_trigger | 4 | 當(dāng)有4個(gè)未進(jìn)行Compact的文件時(shí),達(dá)到觸發(fā)Compact的條件 |
| level0_slowdown_writes_trigger | 20 | 當(dāng)有20個(gè)未進(jìn)行Compact的文件時(shí),觸發(fā)RocksDB,減慢寫(xiě)入速度 |
| level0_stop_writes_trigger | 24 | 當(dāng)有24個(gè)未進(jìn)行Compact的文件時(shí),觸發(fā)RocksDB停止寫(xiě)入文件,此時(shí)會(huì)盡快的Compact Level-0層文件 |
- 如果是Level-1+層,會(huì)去計(jì)算每一層未進(jìn)行Compact文件的總Size,然后再和這一層的”容量值”做對(duì)比,得到一個(gè)比值,這個(gè)值就是該層的 CompactScore ,也就是說(shuō)對(duì)于Level-1+層,Compact 觸發(fā)條件是看這一層文件的大小而不是個(gè)數(shù)。Score = level_bytes / MaxBytesForLevel(level)
對(duì)于Level-1+層,每一層的最大Bytes 是如何計(jì)算出來(lái)的?
Level-1 層 文件總大小由 max_bytes_for_level_base 參數(shù)控制,而 Level-2 層的大小通過(guò): Level_max_bytes[N] = Level_max_bytes[N-1] * max_bytes_for_level_multiplier^(N-1)*max_bytes_for_level_multiplier_additional[N-1] 計(jì)算得出:
| max_bytes_for_level_base | 10485760 | 用于指定Level-1 層總大小,超過(guò)這個(gè)值滿(mǎn)足觸發(fā)Compact條件 |
| max_bytes_for_level_multiplier | 10 | 每一層最大Bytes 乘法因子 |
| max_bytes_for_level_multiplier_addtl[2] | 1 | Level-2 層總大小調(diào)整參數(shù) |
| max_bytes_for_level_multiplier_addtl[3] | 1 | Level-3 層總大小調(diào)整參數(shù) |
| max_bytes_for_level_multiplier_addtl[4] | 1 | Level-4 層總大小調(diào)整參數(shù) |
| max_bytes_for_level_multiplier_addtl[5] | 1 | Level-5 層總大小調(diào)整參數(shù) |
| max_bytes_for_level_multiplier_addtl[6] | 1 | Level-6 層總大小調(diào)整參數(shù) |
在進(jìn)行Compact的時(shí)候,會(huì)選擇哪些文件進(jìn)行Compact操作呢?
對(duì)于Level-0層文件,RocksDB總是選擇所有的文件進(jìn)行Compact操作,因?yàn)長(zhǎng)evel-0層的文件之間,可能會(huì)有key范圍的重疊。?
對(duì)于Level-N (N>1)層的文件,會(huì)先按照文件大小排序(冒泡排序),選出最大的文件,并計(jì)算這個(gè)文件Key 的起止范圍,通過(guò)這個(gè)范圍查找Level-N+1層文件,把選出的Level-N 文件和Level-N+1 文件做為輸入,并且在Level-N+1新建一個(gè)或多個(gè)SST文件作為輸出。?
可以通過(guò)設(shè)置max_background_compactions 大于1 來(lái)使用并行Compact,不過(guò)這個(gè)并行Compact 不能作用到Level-0層。
如何查看RocksDB內(nèi)部狀態(tài)?
一般情況下內(nèi)部狀態(tài)會(huì)定時(shí)dump出來(lái)存放到LOG文件里,這個(gè)時(shí)間可以通過(guò):stats_dump_period_sec 來(lái)控制這個(gè)dump內(nèi)部狀態(tài)的頻率,如果是TRedis V1.2.9 版本以上可以通過(guò) rocksprop rocksdb.cfstats 得到這些信息:
總結(jié)
以上是生活随笔為你收集整理的聊聊RocksDB Compact的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: MySQL常用命令大全(完整)
- 下一篇: vscode 软件 git提交代码步骤