LevelDB源碼解析6. 版本概念
什麼是Version, VersionEdit, VersionSet?
Version是什麼?
假設當前數據塊如下圖所示:
這個時候發現有需要合併的數據塊。那麼合併之後結果就是:
如果只看有變動的部分,結果好像是:
由於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一直增加,又不刪除,那時間一長,豈不會導致文件數目相當多?
所以這個時候的解決方案是:當某箇舊的Verions不再被讀的時候。這些舊的Version就會被刪除了。
萬一舊的Version正在被寫,怎麼辦呢?
別開玩笑了。sstable一旦生成,除了刪除之外,是不可能去寫入的。
引用
淺析 Bigtable 和 LevelDB 的實現
推薦閱讀:
※LevelDB源碼解析10.創建VersionSet
※LevelDB源碼解析11.文件序號
※LevelDB源碼解析9. WAL LOG讀取
※[跟吉姆一起讀LevelDB]10.Delete與Snapshot
※[跟吉姆一起讀LevelDB]11.Iterator與Compaction(1)