元數(shù)據(jù)作用
Hbase有存儲(chǔ)在zookeeper的metadata來定位RegionServer,
而LevelDB也通過元數(shù)據(jù)管理模塊去感知每一層有哪些SST文件;快速的定位某條數(shù)據(jù)所在的SST文件;以及重啟后恢復(fù)到之前的狀態(tài)。
作用概括如下:
記錄Compaction相關(guān)信息,使得Compaction過程能在需要的時(shí)候被觸發(fā);
維護(hù)SST文件索引信息及層次信息,為整個(gè)LevelDB的讀、寫、Compaction提供數(shù)據(jù)結(jié)構(gòu)支持;
負(fù)責(zé)元信息數(shù)據(jù)的持久化,使得整個(gè)庫可以從進(jìn)程重啟或機(jī)器宕機(jī)中恢復(fù)到正確的狀態(tài);
記錄LogNumber,Sequence,下一個(gè)SST文件編號(hào)等狀態(tài)信息;
以版本的方式維護(hù)元信息,使得Leveldb內(nèi)部或外部用戶可以以快照的方式使用文件和數(shù)據(jù)。
實(shí)現(xiàn)
LeveDB用Version表示一個(gè)版本的元信息,Version中主要包括一個(gè)FileMetaData指針的二維數(shù)組,分層記錄了所有的SST文件信息。FileMetaData數(shù)據(jù)結(jié)構(gòu)用來維護(hù)一個(gè)文件的元信息,包括文件大小,文件編號(hào),最大最小值,引用計(jì)數(shù)等,其中引用計(jì)數(shù)記錄了被不同的Version引用的個(gè)數(shù),保證被引用中的文件不會(huì)被刪除。
VersionSet是一個(gè)Version構(gòu)成的雙向鏈表,這些Version按時(shí)間順序先后產(chǎn)生,記錄了當(dāng)時(shí)的元信息,鏈表頭指向當(dāng)前最新的Version,同時(shí)維護(hù)了每個(gè)Version的引用計(jì)數(shù),被引用中的Version不會(huì)被刪除,其對(duì)應(yīng)的SST文件也因此得以保留,通過這種方式,使得LevelDB可以在一個(gè)穩(wěn)定的快照視圖上訪問文件。VersionSet中除了Version的雙向鏈表外還會(huì)記錄一些如LogNumber,Sequence,下一個(gè)SST文件編號(hào)的狀態(tài)信息。

Version更新
leveldb中只要文件變動(dòng)應(yīng)用在舊的Version上可以得到新的Version。而這個(gè)更新信息都保存在VersionEdit中。
即:
Version N + VersionEdit = Version N+1
進(jìn)程崩潰以及恢復(fù)
為了避免進(jìn)程崩潰或機(jī)器宕機(jī)導(dǎo)致的數(shù)據(jù)丟失,LevelDB需要將元信息數(shù)據(jù)持久化到磁盤,承擔(dān)這個(gè)任務(wù)的就是Manifest文件。可以看出每當(dāng)有新的Version產(chǎn)生都需要更新Manifest,很自然的發(fā)現(xiàn)這個(gè)新增數(shù)據(jù)正好對(duì)應(yīng)于VersionEdit內(nèi)容。
在Manifest中的一次增量?jī)?nèi)容稱作一個(gè)Block,其內(nèi)容如下:
Manifest Block := N * Item
Item := [kComparator] comparator
or [kLogNumber] 64位log_number
or [kPrevLogNumber] 64位pre_log_number
or [kNextFileNumber] 64位next_file_number_
or [kLastSequence] 64位last_sequence_
or [kCompactPointer] 32位level + 變長(zhǎng)的key
or [kDeletedFile] 32位level + 64位文件號(hào)
or [kNewFile] 32位level + 64位 文件號(hào) + 64位文件長(zhǎng)度 + smallest key + largest key</pre>
last_sequence
記錄了向leveldb中寫入的記錄總數(shù),寫數(shù)據(jù)時(shí)被使用
WriteBatchInternal::SetSequence(updates, last_sequence + 1);//對(duì)WriteBatch的序號(hào)+1
last_sequence += WriteBatchInternal::Count(updates);//加上此次寫入的記錄數(shù),即為此時(shí)已經(jīng)寫入的記錄總數(shù)
/* ...... */
versions_->SetLastSequence(last_sequence);//將其保存在VersionSet中</pre>