LevelDB源碼解析6. 版本概念

什麼是Version, VersionEdit, VersionSet?

Version是什麼?

假設當前數據塊如下圖所示:

這個時候發現有需要合併的數據塊。那麼合併之後結果就是:

如果只看有變動的部分,結果好像是:

合併SSTable文件

由於levelDB規定,舊有的sst文件是不能被修改的。直覺上的可能會認為當

{17 40}{12 19}{22 45}

在合併完之後,會被刪除掉。但是,需要考慮這種情況。因為LevelDB是支持多線程的。也就是說,當合併操作在讀這三個sst文件的時候。其他的讀操作也有可能落在這三個文件上。所以,刪除文件的時候,需要等到這三個sst文件的引用ref = 0的時候才可以。

所以生成的文件列表就是這樣:

合併之後的文件列表

這個時候會發現?啥?舊的文件和新的文件都是放在一起的。那如何區分這些文件。用戶的Get操作到來的時候,如果還是要把:

{17 40}{12 19}{22 45}{12 45}

這四個文件掃描一遍。那合併還有什麼意義。

因此,面臨的問題是:

保留舊有的文件,是為了支持合併時正在進行的讀請求。Q: 如何區分合併之前的舊文件與新文件?

這個時候,一種自然的想法,就是引入版本控制。

  • 舊有的文件組成一個版本Version。
  • 合併操作稱之為VersionEdit。
  • 舊的版本與新的版本可以共存。當新版本完成的之後。用戶發起來的請求就到新的版本上。這個新的版本就叫current。
  • 假設Version1在生成Version2的時候,Version1正在服務很多讀請求。Version1自然不能丟。
    • 當Version2生成好了之後,Version2也開始服務很多讀請求。
    • Version2到達某一時刻,也會開始進行合併,生成Version3。由於Version2還在服務讀請求。自然不能丟棄。

正在工作的整體就是{version1, version2, version3}.

這個服務於當前DB的Version的集合,就稱之為VersionSet。通過下圖可以看明白。

Version/VersionEdit/VersionSet概念一覽

這個時候可能還會有一個問題:

如果Version一直增加,又不刪除,那時間一長,豈不會導致文件數目相當多?

所以這個時候的解決方案是:當某箇舊的Verions不再被讀的時候。這些舊的Version就會被刪除了。

萬一舊的Version正在被寫,怎麼辦呢?

別開玩笑了。sstable一旦生成,除了刪除之外,是不可能去寫入的。

引用

淺析 Bigtable 和 LevelDB 的實現


推薦閱讀:

LevelDB源碼解析10.創建VersionSet
LevelDB源碼解析11.文件序號
LevelDB源碼解析9. WAL LOG讀取
[跟吉姆一起讀LevelDB]10.Delete與Snapshot
[跟吉姆一起讀LevelDB]11.Iterator與Compaction(1)

TAG:LevelDB | 源碼閱讀 |