閱讀982 返回首頁    go 阿裏雲 go 技術社區[雲棲]


“寫優化”的數據結構(3):small-splittable-tree

作者:一工

如果你感到buffered b-tree 或者 x–y tree還是有點複雜,這裏還有簡單的。

如果不走tree-like派係,那就走短、平、快的small-splittable-tree的路子,甚至可以玩small-splittable-list。

 

短就是每個tree單元要小。
平就是tree高度要低。
快就是分裂起來要快(compaction)。
這裏的tree可以是b-tree或其他的tree結構都沒問題,但在分裂起來,一定要快,不能hang住寫線程。

 

如果你嫌tree結構有高度,還是複雜,那可以來簡單的small-splittable-list,也就是所有數據插入完畢,最終是個順序的list,這個list由多個segment構成,任何兩個segment之間不會有區間重疊。

 

write
——–
每個segment反映到磁盤就是一個文件,比如1.SSL。
這個SSL文件由2部分組成:header和blocks。
header記錄區間信息,比如: <pivot1, blockid1> … <pivotn, blockidn>,用於數據歸屬block查找。
block裏存放的是key-value數據(追加寫),每個block大小是固定的(比如256KB),當block滿了,就分裂成2個block,當一個SSL裏的block都滿了(個數等於 SSL-size/block-size),則對這個SSL進行分裂,這個分裂過程也是很快的,沒有數據merge過程。

 

read
——
首先根據key定位到你屬於哪個SSL,然後根據header定位到你屬於哪個block,這樣就搞定了。

small-splittable-list基本就是在往AOF靠攏,但是讀起來是很快的。

這種數據結構的缺點就是page cache利用率不高,共享部分太少了,如果是tree,從root到某些inner-node的路徑是可共享的,隻好做記錄級緩存了,kernel幫不了你。

 

 

 

小結

 

做“寫優化”的數據結構讀不一定慢的。
比如在寫的過程中,你已經走了root-node1-node2…-nodex這條path,可認為它已在page cache裏,當你讀的時候,root無需從磁盤讀取,node1也無需從磁盤,這樣“讀”就揩“寫”的油。反過來,“寫”也可以揩”讀“的油,所以即使在讀寫混合的時候,仍可互利。

如果node大小為4MB(leaf節點可設置的更大些),一個高度為6的tree就是TB級了,這樣leaf節點是很少被touch到的,所以在page cache裏的基本都是inner node,很爽了 :D

如果你“嫌棄”page cache的機製,可以嚐試自己的cache + Direct IO (cascadb用的AIO)這條路。

期待更多的引擎來嚐試下buffered tree!

BTW:大塊寫在SSD上的好處就是Write amplification(https://en.wikipedia.org/wiki/Write_amplification)的降低。

最後更新:2017-04-03 07:57:05

  上一篇:go 連載:麵向對象葵花寶典:思想、技巧與實踐(34) - DIP原則
  下一篇:go [數據庫]MySQL Hash索引和B-Tree索引的區別