kudu 存储引擎简析
本文由??網(wǎng)易云?發(fā)布。
?
1?概述
本文主要介紹kudu底層存儲引擎的數(shù)據(jù)組織方式,先看整體結(jié)構(gòu)如下:
一張表會分成若干個tablet , 每個tablet 包括MetaData 元信息及若干個RowSet , RowSet 包含一個MemRowSet 及若干個DiskRowSet , DiskRowSet 中 包 含 一 個 BloomFile 、 Ad_hoc Index 、 BaseData 、 DeltaMem 及 若 干 個 RedoFile 和UndoFile(UndoFile一般情況下只有一個)。
?
MemRowSet用于新數(shù)據(jù)insert及已在MemRowSet中的數(shù)據(jù)的更新,一個MemRowSet寫滿后會將數(shù)據(jù)刷到磁盤形成若干個DiskRowSet。
DiskRowSet用于老數(shù)據(jù)的mutation,后臺定期對DiskRowSet做compaction,以刪除沒用的數(shù)據(jù)及合并歷史數(shù)據(jù),減少查詢過程中的IO開銷。
BloomFile根據(jù)一個DiskRowSet中的key生成一個bloom filter,用于快速模糊定位某個key是否在DiskRowSet中存在。Ad_hoc Index是主鍵的索引,用于定位key在DiskRowSet中的具體哪個偏移位置。
BaseData 是 MemRowSet flush 下 來 的 數(shù) 據(jù) , 按 列 存 儲 , 按 主 鍵 有 序 。UndoFile是基于BaseData之前時間的歷史數(shù)據(jù),通過在BaseData上apply UndoFile中的記錄,可以獲得歷史數(shù)據(jù)。RedoFile是基于BaseData之后時間的mutation記錄,通過在BaseData上apply RedoFile中的記錄,可獲得較新的數(shù)據(jù)。DeltaMem用于DiskRowSet中數(shù)據(jù)的mutation,先寫到內(nèi)存中,寫滿后flush到磁盤形成RedoFile。
?
2?MemRowSet
MemRowSet的數(shù)據(jù)組織形式是一顆B+Tree,結(jié)構(gòu)如下:
這顆B+樹實現(xiàn)的比較簡單,因為它沒有update跟delete操作,kudu在MemRowSet中中數(shù)據(jù)的mutation采用類似append log 方式,在base數(shù)據(jù)上有個mutation指針,所有的后續(xù)mutation操作都掛在這個指針上了。
雖然只有插入,但是也會出現(xiàn)節(jié)點滿時需要做split,同時可能有讀操作也在同步進行,kudu使用AtomicVersion(原子變量+位移)實現(xiàn)了一個鎖。樹的度跟cpu的CACHELINE_SIZE有關(guān),是為了讓一個節(jié)點僅讀取一次cpu cache。
樹的檢索是先找到key所在的LeafNode,然后在LeafNode內(nèi)部進行二分查找,LeafNode間有指針進行串聯(lián),為了方便scan,掃整個MemRowSet一般通過一個空串的key找到第一個LeafNode,然后依次讀數(shù)據(jù)。
?
3?DiskRowSet
這部分是kudu存儲部分最復(fù)雜的東西,分為兩個部分來講,DiskRowSet間的組織,DiskRowSet內(nèi)數(shù)據(jù)組織,先看DiskRowSet 間怎么組織的。
?
3.1?DiskRowSet間組織
一個tablet隨這數(shù)據(jù)的不斷寫入會包含很多個DiskRowSet,每個DiskRowSet上有min_key、max_key標(biāo)明key的范圍,如果要查找一個key在哪個DiskRowSet上依次遍歷每個DiskRowSet效率是很低的,這種情況線段樹這種數(shù)據(jù)結(jié)構(gòu)是很適合做range索引的,將所有的DiskRowSet形成一顆線段樹,結(jié)構(gòu)如下:
?
其實就是一個二叉平衡樹,每次從所有range(最小的min_key跟最大的max_key)的中間key做split,將range跨域左右子樹的
DiskRowSet(即split point落在DiskRowSet的min_key與max_key之間)放到overlap rowsets中去。這顆樹實現(xiàn)的也很簡單, 因為它只做查詢用,生成后就不會變動,若遇到MemRowSet flush或DiskRowSet Merge Compaction就直接重新生成一顆新樹。
這個樹主要用于在讀或?qū)懙臅r候定位某個或若干個key 在哪些DiskRowSet 的range 范圍內(nèi), 只能通過DiskRowSet 的min_key/max_key做一層模糊過濾,是否正在存在需要做進一步檢查。
?
3.2?DiskRowSet內(nèi)數(shù)據(jù)組織
一個DiskRowSet大體數(shù)據(jù)組織上面概述中已介紹過,其中DeltaMem跟MemRowSet在內(nèi)存中的組織方式是一樣的,都是B+Tree,而在磁盤上的存儲都是放在CFile中的,下面我們看看CFile的文件格式:
?
?
CFile包含Header、Data、Index、Footer幾塊,其中Data部分起始部分是為空值的條目建立的bitmap,僅針對可為null的
column,對于主鍵是沒有這個的,bitmap就是以那些值為null的RowId建立起來的位圖,這樣Data中就不用存這些空值。data部分不同的column類型文件會有不同的編碼方式:
?
對于ad_hoc文件使用的是prefix,delta file使用的是plain,bloomfile使用的是plain。每種BlockBuilder在處理一定量數(shù)據(jù)后就會append到Data中。
Index有兩種,posidx_index是根據(jù)RowId找到在Data中的偏移,validx index是根據(jù)key的值找到在Data中的偏移,validx只針對只有一個column為key的情況,這個時候DiskRowSet沒有Ad_hoc索引,使用validex來代替。這兩個index內(nèi)部實現(xiàn)是一個B- Tree,index不一定是連續(xù)的,在達(dá)到一定長度后就會刷盤,而內(nèi)部可以區(qū)分是中間節(jié)點還是葉子節(jié)點及其孩子節(jié)點的位置。
Footer是記錄了CFile的元信息,包括posidx_index、validx_index兩棵樹根節(jié)點所在位置,數(shù)據(jù)條目、編碼、壓縮方式等。下面看看DiskRowSet數(shù)據(jù)在磁盤上的分布:
?
在磁盤上每個DiskRowSet有若干個***.metadata及***.data文件,metadata文件記錄的是DiskRowSet的元信息,主要包括哪些block及block在data中的位置,上圖為block與DiskRowSet中各部分的映射關(guān)系,在寫磁盤是通過container來寫,每個container 可以寫很大一塊連續(xù)的磁盤空間, 用于給某個CFile寫數(shù)據(jù), 當(dāng)一個CFile寫完后會將container歸還給BlockManager, 這時container就可以用于下個CFile寫數(shù)據(jù)了,當(dāng)BlockManager中沒有container可用時會新建一個container給新來的CFile使用。
?
對于新建block先看看有無container可用,若沒有目前默認(rèn)是在所有配置中的data_dir中隨機選取一個dir中建一個新的metadata 及data文件。先寫data,block落盤后再寫metadata。
?
對于kudu底層數(shù)據(jù)存儲就介紹到這里,希望對大家有所幫助。
?
?
想要了解網(wǎng)易大數(shù)據(jù),請戳這里網(wǎng)易大數(shù)據(jù)|專業(yè)的私有化大數(shù)據(jù)平臺
?
了解 網(wǎng)易云 :
網(wǎng)易云官網(wǎng):https://www.163yun.com/
新用戶大禮包:https://www.163yun.com/gift
網(wǎng)易云社區(qū):https://sq.163yun.com/
?
總結(jié)
以上是生活随笔為你收集整理的kudu 存储引擎简析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: tornado框架的get方法传递参数
- 下一篇: Spring MVC 中的 contro