一 RocksDB的磁盤數(shù)據(jù)組織層次
1 磁盤文件的組織方式
rocksdb在磁盤上的文件是分為多層的寥枝,分別叫做level-0, level-1等等
level0上包含的文件锨推,是由內(nèi)存中的memtable dump到磁盤上生成的既琴,單個文件內(nèi)部按key有序,文件之間無序。
其它level上的多個文件都是按照key有序的柑船。
2 data range partition
非0 level上的key佃延,按序分片现诀,保存在不同的文件中。
3 key在SST文件中查找
每個level的文件都是整體有序履肃,并且文件內(nèi)有序的仔沿。
要在某個level上查找某個key時:
- 先根據(jù)每個文件的start/end key對所有文件進(jìn)行二分查找來確定哪些文件可能包含key
- 再通過二分查找在候選的文件中定位key的準(zhǔn)確位置
這是一次對一個level上所有文件的二分查找的過程。
二 數(shù)據(jù)壓縮 Compaction
1 L0 compaction
當(dāng)L0的文件數(shù)量達(dá)到level0_file_num_compaction_trigger的值時尺棋,觸發(fā)L0和L1的合并封锉。通常必須將所有L0的文件合并到L1中,因?yàn)長0的文件的key是有交疊的(overlapping)膘螟。
2 高層Compaction
當(dāng)L0 compaction完成后成福,L1的文件總size或者文件數(shù)量可能會超過閾值,觸發(fā)L1向L2的合并荆残。從L1至少選擇一個文件奴艾,合并到L2中key有交疊的文件中。
同樣的内斯,合并后可能會觸發(fā)下一各level的compaction蕴潦。
合并后的L3也需要做Compaction.
3 并行Compaction
max_background_compactions控制了并行compaction的最大數(shù)量。
4 L0 subcompaction
L0向L1的compaction不可以與其他level compaction并行俘闯。這可能成為整體compaction速度的瓶頸潭苞,可以通過設(shè)置max_subcompactions來加速L0到L1的compaction。
5 Compaction的選擇策略
當(dāng)多個level都滿足觸發(fā)compaction的條件真朗,rocksdb通過計(jì)算得分來選擇先做哪一個level的compaction萄传。
- 對于非0 level,score = 該level文件的總長度 / 閾值。已經(jīng)正在做compaction的文件不計(jì)入總長度中秀菱。
- 對于L0振诬,score = max{文件數(shù)量 / level0_file_num_compaction_trigger, L0文件總長度 / max_bytes_for_level_base} 并且 L0文件數(shù)量 > level0_file_num_compaction_trigger衍菱。
得分最高的level有限做compaction赶么。
6 compaction觸發(fā)閾值
每一層的compaction閾值設(shè)置策略由level_compaction_dynamic_level_bytes來決定。
當(dāng)level_compaction_dynamic_level_bytes為false
L1 觸發(fā)閾值:max_bytes_for_level_base
下面的level觸發(fā)閾值通過公式計(jì)算:Target_Size(Ln+1) = Target_Size(Ln) * max_bytes_for_level_multiplier * max_bytes_for_level_multiplier_additional[n]. max_bytes_for_level_multiplier_additional
例如:
max_bytes_for_level_base = 16384
max_bytes_for_level_multiplier = 10
max_bytes_for_level_multiplier_additional = 1
那么每個level的觸發(fā)閾值為 L1, L2, L3 and L4 分別為 16384, 163840, 1638400, and 16384000
當(dāng)level_compaction_dynamic_level_bytes為true
最后一個level的文件長度總是固定的脊串。
上面level觸發(fā)閾值通過公式計(jì)算:Target_Size(Ln-1) = Target_Size(Ln) / max_bytes_for_level_multiplier
如果計(jì)算得到的值小于 max_bytes_for_level_base / max_bytes_for_level_multiplier辫呻, 那么該level將維持為空,L0做compaction時將直接merge到第一個有合法閾值的level上琼锋。
例如:
max_bytes_for_level_base = 1G
num_levels = 6
level 6 size = 276G
那么從L1到L6的觸發(fā)閾值分別為:0放闺, 0, 0.276G缕坎, 2.76G怖侦, 27.6G,276G谜叹。
這樣分配匾寝,保證了穩(wěn)定的LSM-tree結(jié)構(gòu)。并且有90%的數(shù)據(jù)存儲在最后一層荷腊,9%的數(shù)據(jù)保存在倒數(shù)第二層艳悔。
參考資料:官方wiki