??RocksDB內部有WAL log文件,此外,LSM tree還包含了一些SST files。每經過一次compaction,產出的新文件都會添加到SST files中,而輸入的SST file會被刪除。然而,compaction輸入的SST file并不是立即就從SST file集合中刪除,因為有可能在這些SST file上正進行著get or iterator操作。只有當冗余的SST file上沒有任何操作的時候,才會執(zhí)行真正的刪除文件操作。接下來,我們會詳細介紹怎么跟進SST file上的讀寫等操作信息。
??LSM tree的文件信息保存在一個命名為version的數據結構中。當compaction or memtable flush結束后,SST file就會更新,此時,RocksDB就會為最新的LSM tree創(chuàng)建一個新的version來記錄SST file信息。在某一個時刻,只會有一個“current” version數據結構來記錄最新LSM tree的文件信息。get or iterator操作會使用這個version記錄的文件來執(zhí)行完get or iterator的過程。在get or iterator執(zhí)行過程中涉及到的所有SST file都必須保留。如果一個version上沒有任何get or iterator操作,那么這個version就會被drop掉,所有沒有任何version記錄的SST files也都會被刪除掉。
??剛開始時version記錄了三個文件:
v1={f1, f2, f3} (current)
files on disk: f1, f2, f3
??這時一個iterator操作使用了v1
v1={f1, f2, f3} (current, used by iterator1)
files on disk: f1, f2, f3
??此時,發(fā)生了memtable flush,創(chuàng)建了一個新的version和 file 4
v2={f1, f2, f3, f4} (current)
v1={f1, f2, f3} (used by iterator1)
files on disk: f1, f2, f3, f4
??執(zhí)行了compaction操作,將f2 、f3、f4 compaction為 f5,產生最新的version3
v3={f1, f5} (current)
v2={f1, f2, f3, f4}
v1={f1, f2, f3} (used by iterator1)
files on disk: f1, f2, f3, f4, f5
??我們可以看到,v2既不是最新的version,也沒有任何讀操作使用,所以v2以及f4將被刪除。f1、f2、f3在v1中,v1仍然被iterator1使用,所以無法刪除。
v3={f1, f5} (current)
v1={f1, f2, f3} (used by iterator1)
files on disk: f1, f2, f3, f5
??加入此時,iterator1結束了,則最新狀態(tài)為
v3={f1, f5} (current)
v1={f1, f2, f3}
files on disk: f1, f2, f3, f5
??此時,v1既不是最新的version,也沒有被任何操作引用,所以即將被刪除,f2和f3也隨之刪除
v3={f1, f5} (current)
files on disk: f1, f5
??這些邏輯是通過引用計數來實現的。每個SST file和version都有一個引用計數。當創(chuàng)建一個version時,會遞增所有引用的SST file的引用計數。當一個version沒有被使用時,它所包含的所有SST file的引用計數丟會遞減1。如果一個文件的引用計數為0,那么就可以被刪除了。
??類似,每個version也都有一個引用計數。當創(chuàng)建一個version時,那這個version就是最新的version,引用計數遞增1。如果一個version不再是最新的version時,其引用計數會遞減1。在一個version上執(zhí)行的任何操作都會將其引用計數遞增1,這些操作計數后會將其引用計數遞減1。當一個version的引用計數為0時,那么這個version就要被刪除掉。如果一個version上有操作在執(zhí)行或者是最新的version,那么他的引用計數就永遠不會是0,也無法被刪除。
??有時候,reader操作戶直接引用一個version,比如執(zhí)行compaction操作時的輸入version。更多情況下,reader是通過一個命名為super version的數據結構來引用version,這個super version會記錄memtables和version的引用計數,super version其實就是a whole view of the DB。在使用super version來操作version的引用計數時,reader只需要對一個引用計數執(zhí)行遞增和遞減操作就可以了。
??RocksDB的所有version信息記錄在VersionSet中,這個數據結構也同時記錄了哪個version是當前version。由于每個column family都有一個單獨的LSM樹,所以每個column family都有一個version list(其中一個是當前version)。不過,每個DB中僅且只有一個VersionSet來記錄所有column family的version s信息。