?
LevelDb本質(zhì)上是一套存儲(chǔ)系統(tǒng)以及在這套存儲(chǔ)系統(tǒng)上提供的一些操作接口。為了便于理解整個(gè)系統(tǒng)及其處理流程,我們可以從兩個(gè)不同的角度來(lái)看待LevleDb:靜態(tài)角度和動(dòng)態(tài)角度。從靜態(tài)角度,可以假想整個(gè)系統(tǒng)正在運(yùn)行過(guò)程中(不斷插入刪除讀取數(shù)據(jù)),此時(shí)我們給LevelDb照相,從照片可以看到之前系統(tǒng)的數(shù)據(jù)在內(nèi)存和磁盤(pán)中是如何分布的,處于什么狀態(tài)等;從動(dòng)態(tài)的角度,主要是了解系統(tǒng)是如何寫(xiě)入一條記錄,讀出一條記錄,刪除一條記錄的,同時(shí)也包括除了這些接口操作外的內(nèi)部操作比如compaction,系統(tǒng)運(yùn)行時(shí)崩潰后如何恢復(fù)系統(tǒng)等等方面。
本節(jié)所講的整體架構(gòu)主要從靜態(tài)角度來(lái)描述,之后接下來(lái)的幾節(jié)內(nèi)容會(huì)詳述靜態(tài)結(jié)構(gòu)涉及到的文件或者內(nèi)存數(shù)據(jù)結(jié)構(gòu),LevelDb日知錄后半部分主要介紹動(dòng)態(tài)視角下的LevelDb,就是說(shuō)整個(gè)系統(tǒng)是怎么運(yùn)轉(zhuǎn)起來(lái)的。
LevelDb作為存儲(chǔ)系統(tǒng),數(shù)據(jù)記錄的存儲(chǔ)介質(zhì)包括內(nèi)存以及磁盤(pán)文件,如果像上面說(shuō)的,當(dāng)LevelDb運(yùn)行了一段時(shí)間,此時(shí)我們給LevelDb進(jìn)行透視拍照,那么您會(huì)看到如下一番景象:
圖1.1:LevelDb結(jié)構(gòu)
從圖中可以看出,構(gòu)成LevelDb靜態(tài)結(jié)構(gòu)的包括六個(gè)主要部分:內(nèi)存中的MemTable和Immutable MemTable以及磁盤(pán)上的幾種主要文件:Current文件,Manifest文件,log文件以及SSTable(Sorted String table)文件。當(dāng)然,LevelDb除了這六個(gè)主要部分還有一些輔助的文件,但是以上六個(gè)文件和數(shù)據(jù)結(jié)構(gòu)是LevelDb的主體構(gòu)成元素。
LevelDb的Log文件和Memtable與Bigtable論文中介紹的是一致的,當(dāng)應(yīng)用寫(xiě)入一條Key:Value記錄的時(shí)候,LevelDb會(huì)先往log文件里寫(xiě)入,成功后將記錄插進(jìn)Memtable中,這樣基本就算完成了寫(xiě)入操作,因?yàn)橐淮螌?xiě)入操作只涉及一次磁盤(pán)順序?qū)懞鸵淮蝺?nèi)存寫(xiě)入,所以這是為何說(shuō)LevelDb寫(xiě)入速度極快的主要原因。
Log文件在系統(tǒng)中的作用主要是用于系統(tǒng)崩潰恢復(fù)而不丟失數(shù)據(jù),假如沒(méi)有Log文件,因?yàn)閷?xiě)入的記錄剛開(kāi)始是保存在內(nèi)存中的,此時(shí)如果系統(tǒng)崩潰,內(nèi)存中的數(shù)據(jù)還沒(méi)有來(lái)得及Dump到磁盤(pán),所以會(huì)丟失數(shù)據(jù)(Redis就存在這個(gè)問(wèn)題)。為了避免這種情況,LevelDb在寫(xiě)入內(nèi)存前先將操作記錄到Log文件中,然后再記入內(nèi)存中,這樣即使系統(tǒng)崩潰,也可以從Log文件中恢復(fù)內(nèi)存中的Memtable,不會(huì)造成數(shù)據(jù)的丟失。
當(dāng)Memtable插入的數(shù)據(jù)占用內(nèi)存到了一個(gè)界限后,需要將內(nèi)存的記錄導(dǎo)出到外存文件中,LevleDb會(huì)生成新的Log文件和Memtable,原先的Memtable就成為Immutable Memtable,顧名思義,就是說(shuō)這個(gè)Memtable的內(nèi)容是不可更改的,只能讀不能寫(xiě)入或者刪除。新到來(lái)的數(shù)據(jù)被記入新的Log文件和Memtable,LevelDb后臺(tái)調(diào)度會(huì)將Immutable Memtable的數(shù)據(jù)導(dǎo)出到磁盤(pán),形成一個(gè)新的SSTable文件。SSTable就是由內(nèi)存中的數(shù)據(jù)不斷導(dǎo)出并進(jìn)行Compaction操作后形成的,而且SSTable的所有文件是一種層級(jí)結(jié)構(gòu),第一層為L(zhǎng)evel 0,第二層為L(zhǎng)evel 1,依次類推,層級(jí)逐漸增高,這也是為何稱之為L(zhǎng)evelDb的原因。
SSTable中的文件是Key有序的,就是說(shuō)在文件中小key記錄排在大Key記錄之前,各個(gè)Level的SSTable都是如此,但是這里需要注意的一點(diǎn)是:Level 0的SSTable文件(后綴為.sst)和其它Level的文件相比有特殊性:這個(gè)層級(jí)內(nèi)的.sst文件,兩個(gè)文件可能存在key重疊,比如有兩個(gè)level 0的sst文件,文件A和文件B,文件A的key范圍是:{bar, car},文件B的Key范圍是{blue,samecity},那么很可能兩個(gè)文件都存在key=”blood”的記錄。對(duì)于其它Level的SSTable文件來(lái)說(shuō),則不會(huì)出現(xiàn)同一層級(jí)內(nèi).sst文件的key重疊現(xiàn)象,就是說(shuō)Level L中任意兩個(gè).sst文件,那么可以保證它們的key值是不會(huì)重疊的。這點(diǎn)需要特別注意,后面您會(huì)看到很多操作的差異都是由于這個(gè)原因造成的。
SSTable中的某個(gè)文件屬于特定層級(jí),而且其存儲(chǔ)的記錄是key有序的,那么必然有文件中的最小key和最大key,這是非常重要的信息,LevelDb應(yīng)該記下這些信息。Manifest就是干這個(gè)的,它記載了SSTable各個(gè)文件的管理信息,比如屬于哪個(gè)Level,文件名稱叫啥,最小key和最大key各自是多少。下圖是Manifest所存儲(chǔ)內(nèi)容的示意:
圖2.1:Manifest存儲(chǔ)示意圖
圖中只顯示了兩個(gè)文件(manifest會(huì)記載所有SSTable文件的這些信息),即Level 0的Test1.sst和Tes2t.sst文件,同時(shí)記載了這些文件各自對(duì)應(yīng)的key范圍,比如Test1.sst的key范圍是“abc”到“hello”,而文件Test2.sst的key范圍是“bbc”到“world”,可以看出兩者的key范圍是有重疊的。
Current文件是干什么的呢?這個(gè)文件的內(nèi)容只有一個(gè)信息,就是記載當(dāng)前的manifest文件名。因?yàn)樵贚evleDb的運(yùn)行過(guò)程中,隨著Compaction的進(jìn)行,SSTable文件會(huì)發(fā)生變化,會(huì)有新的文件產(chǎn)生,老的文件被廢棄,Manifest也會(huì)跟著反映這種變化,此時(shí)往往會(huì)新生成Manifest文件來(lái)記載這種變化,而Current則用來(lái)指出哪個(gè)Manifest文件才是我們關(guān)心的那個(gè)Manifest文件。
以上介紹的內(nèi)容就構(gòu)成了LevelDb的整體靜態(tài)結(jié)構(gòu),在接下來(lái)的內(nèi)容中,我們會(huì)首先介紹重要文件或者內(nèi)存數(shù)據(jù)的具體數(shù)據(jù)布局與結(jié)構(gòu)。
下一節(jié)介紹LOG文件
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
