上一篇文章討論了HDFS的架構(gòu),特點(diǎn)以及存儲(chǔ)規(guī)劃。本篇文章將談一下Hadoop存儲(chǔ)家族的二當(dāng)家KUDU。我們之前也談到KUDU有和HDFS一樣的水平擴(kuò)展能力以及近似HBase的高效讀寫(xiě)能力,那么會(huì)為什么會(huì)這樣呢,本文中將給出解答。本文將會(huì)從KUDU的架構(gòu)和內(nèi)部機(jī)制,KUDU數(shù)據(jù)存儲(chǔ)方式,KUDU與HDFS和HBase的對(duì)比幾方面進(jìn)行討論。
KUDU的架構(gòu)和內(nèi)部機(jī)制
KUDU是一個(gè)分布式主從架構(gòu)的存儲(chǔ)系統(tǒng),這意味者它有Master-Slave的架構(gòu),不過(guò)實(shí)際上,它的Slave組件叫做Tablet Server,存儲(chǔ)著KUDU中的數(shù)據(jù)。KUDU的架構(gòu)圖如下:
KUDU整體是高可用的,無(wú)論是Master還是Tablet Server都有多臺(tái),它們內(nèi)部采用Raft選舉機(jī)制來(lái)保障誰(shuí)是Leader,誰(shuí)是Follower。
對(duì)于KUDU Master來(lái)說(shuō),它主要存儲(chǔ)Catalog Table, Tablet Server以及Tablets的元數(shù)據(jù)信息。Catalog Table存儲(chǔ)KUDU中Table的Metadata信息。KUDU Master使用采用Raft機(jī)制,為保證選舉的成功性,通常Master需要為奇數(shù)個(gè),一般是3個(gè),在集群規(guī)模比較大時(shí)可設(shè)置為5個(gè)。
對(duì)于Tablet Server, 它主要存儲(chǔ)Tablets以及向外部Client提供服務(wù)。
Tablet的不同副本會(huì)存儲(chǔ)在不同的Tablet Server上,它們也通過(guò)Raft機(jī)制保障誰(shuí)是Leader,誰(shuí)是Follower。對(duì)于一個(gè)特定的Tablet, 只有Leader可以被寫(xiě)入,而Follower只能被讀取。這樣大大提升了讀的效率。然而當(dāng)數(shù)據(jù)寫(xiě)入過(guò)大時(shí),如果有Leader Tablet所在的Tablet Server宕機(jī),那將會(huì)造成大量的寫(xiě)失敗,而在Raft機(jī)制中,Leader只允許提交當(dāng)前時(shí)間片的數(shù)據(jù),因?yàn)楫?dāng)新的Leader選舉產(chǎn)生后,之前寫(xiě)失敗的數(shù)據(jù)也不會(huì)再次寫(xiě)入,只能繼續(xù)寫(xiě)當(dāng)前時(shí)間片以后的新數(shù)據(jù)。這也是為什么Tablet Server節(jié)點(diǎn)宕機(jī)后,有可能造成數(shù)據(jù)一致性的問(wèn)題。
KUDU數(shù)據(jù)存儲(chǔ)方式
那么對(duì)于一個(gè)特定的數(shù)據(jù)表, KUDU里是怎么存儲(chǔ)的呢?參見(jiàn)下圖:
對(duì)于一個(gè)表,KUDU中會(huì)將其若干個(gè)Tablet, 每個(gè)Tablet又包含Metadata以及RowSet。其中Metadata存放Tablets的元數(shù)據(jù)信息,RowSet存儲(chǔ)具體的數(shù)據(jù)。
RowSet是把Tablet切片成更小的單元。RowSet分為兩種,一種在內(nèi)存里,叫MemRowSet,一種flush落地到磁盤(pán)上,叫DiskRowSet。
這兩種RowSet有些區(qū)別,首先,一個(gè)表只有一個(gè)MemRowSet,但是會(huì)有很多個(gè)DiskRowSet。當(dāng)MemRowSet達(dá)到指定大小時(shí)(一般是32M),才會(huì)刷新到磁盤(pán)上形成DiskRowSet。因?yàn)?2M的大小并不大,所以不會(huì)造成HBase中Major Compaction的性能問(wèn)題。
另外,MemRowSet中數(shù)據(jù)是行式存儲(chǔ),實(shí)現(xiàn)形式是B+tree,它的存儲(chǔ)樣式為:
而DiskRowSet為列式存儲(chǔ),它的存儲(chǔ)樣式為:
對(duì)于每一個(gè)DiskRowSet,它包含六個(gè)部分:BloomFile,AdhocIndex,UndoFile,RedoFile,BaseData,DeltaMem。
BloomFile是根據(jù)主鍵生成的一個(gè)Bloom Filter,用于模糊定位數(shù)據(jù)是否在DiskRowSet存在;
AdhocIndex則是主鍵的索引,用于定位主鍵在DiskRowSet的偏移量;
BaseData是上次Flush到磁盤(pán)的數(shù)據(jù);
RedoFile是上次Flush到磁盤(pán)以后發(fā)生的數(shù)據(jù)變化;
UndoFile是上次Flush到磁盤(pán)之前的數(shù)據(jù);
DeltaMem則是RedoFile生成之前的在內(nèi)存和磁盤(pán)交互時(shí)的存儲(chǔ)格式。
DiskRowSet在磁盤(pán)上具體存儲(chǔ)為一個(gè)個(gè)的CFile文件, 需要注意的是,DiskRowSet這六部分并不是存在一個(gè)CFile中,而是獨(dú)立在多個(gè)CFile中的,每一部分都會(huì)形成單獨(dú)的CFile。
但實(shí)際上,無(wú)論是在KUDU Master還是KUDU Tablet Server上,我們見(jiàn)到實(shí)際存儲(chǔ)的都是都是.metadata文件和.data文件,像這種:
CFile文件在哪?和.data還有.metadata文件有什么關(guān)系?他們的關(guān)系像這樣:
.metadata文件記錄的是一個(gè)DiskRowSet中幾部分對(duì)應(yīng)CFile的位置以及映射關(guān)系,而大量的CFile又被Container合并寫(xiě)到一個(gè).data文件中,因此對(duì)于一個(gè)DiskRowSet的正常讀寫(xiě),.metadata文件和.data文件缺一不可。
KUDU與HDFS以及HBase的對(duì)比
對(duì)于HDFS來(lái)說(shuō),無(wú)論讀還是寫(xiě),實(shí)際操作的是底層一個(gè)個(gè)數(shù)據(jù)文件,由于設(shè)計(jì)之初并不對(duì)文件中的內(nèi)容做要求,因此只支持整個(gè)數(shù)據(jù)文件的新增,刪除或者向其中追加新的數(shù)據(jù)。而無(wú)法實(shí)現(xiàn)單條數(shù)據(jù)的更新和刪除,因?yàn)镠DFS根本沒(méi)有辦法定位這條數(shù)據(jù)在哪里,而即便定位了,也需要把整個(gè)數(shù)據(jù)文件刪掉再重建才能把操作完成,這個(gè)代價(jià)太過(guò)昂貴。而如果是離線(xiàn)分析,HDFS倒是很有優(yōu)勢(shì),雖然它不知道某條數(shù)據(jù)在哪里,但是它知道分析用到的整張表在哪里存儲(chǔ)并進(jìn)行快速定位。
對(duì)于HBase來(lái)說(shuō),它底層仍然依賴(lài)于HDFS的文件塊存儲(chǔ),但是它需要實(shí)現(xiàn)快速數(shù)據(jù)快速插入,更新和刪除。那它怎么實(shí)現(xiàn)呢?和KUDU一樣,HBase借用了內(nèi)存來(lái)進(jìn)行處理,在內(nèi)存中有MemStore,所有寫(xiě)入HBase的數(shù)據(jù)都變成一個(gè)Key-Value的鍵值對(duì),當(dāng)然這個(gè)Key不只是一個(gè)字段,而是Rowkey+Column Family+Column Qualifier+Timestamp+Type的組成,而Value是Column Qualifier所對(duì)應(yīng)的值。當(dāng)MemStore到達(dá)一定大小后,會(huì)Flush到磁盤(pán)行程HFile,而HFile對(duì)應(yīng)一個(gè)個(gè)HDFS的BLOCK文件,MemStore以及HFile中要求Key必須是高度有序的,因此可以快速定位數(shù)據(jù),HBase對(duì)表的所有的插入和更新都轉(zhuǎn)換成對(duì)HDFS的HFile文件的創(chuàng)建。這樣一來(lái)數(shù)據(jù)更新和刪除的問(wèn)題解決了,但是要做離線(xiàn)分析就復(fù)雜了,因?yàn)槌薑ey以外的其他數(shù)據(jù)無(wú)法定位,而且將HDFS數(shù)據(jù)文件經(jīng)過(guò)一次轉(zhuǎn)換,在最差情況下可能需要SCAN全表才能找到分析需要的數(shù)據(jù)。
KUDU的數(shù)據(jù)處理流程和HBase有些類(lèi)似,但是為了滿(mǎn)足更高要求的數(shù)據(jù)一致性以及數(shù)據(jù)分析能力,KUDU的數(shù)據(jù)寫(xiě)入過(guò)程比HBase更加復(fù)雜,因此KUDU的隨機(jī)讀寫(xiě)效率是要比HBase差一些的。但是它又有一些新的特性比HBase更優(yōu)秀,例如:
● KUDU的數(shù)據(jù)分區(qū)方式多樣化,而HBase單一化;
● KUDU底層采用本地文件系統(tǒng),而HBase底層采用HDFS;
● KUDU本身就有Catalog Table的機(jī)制,因此和Impala集成時(shí)運(yùn)作效率很高,而HBase這點(diǎn)基本上望塵莫及;
● KUDU的Compaction產(chǎn)生的IO量非常小,不會(huì)產(chǎn)生性能問(wèn)題,而HBase大表的Major Compaction很容易誘發(fā)性能問(wèn)題。
KUDU與HDFS相比,它雖然實(shí)現(xiàn)了數(shù)據(jù)的快速更新,刪除等需求,但是它也有以下不足的地方:
● KUDU的穩(wěn)定性較差,節(jié)點(diǎn)故障或者磁盤(pán)損壞都會(huì)導(dǎo)致數(shù)據(jù)一致性風(fēng)險(xiǎn);
● KUDU Compaction的文件小但是數(shù)量多,因此系統(tǒng)的最大打開(kāi)文件數(shù)限制需要設(shè)置的比較大;
● KUDU運(yùn)行時(shí)需要較多的內(nèi)存。
KUDU目前最新版本已經(jīng)發(fā)展到1.11.1。除上述情況外,仍然存在一些使用上的限制:
◆ 表創(chuàng)建后,主鍵不能修改;
◆ 主鍵列大小不能大于16K,且必須在非主鍵列之前;
◆ KUDU中的表最大只能支持300列;
◆ 不能使用Alter Table改變現(xiàn)有列的類(lèi)型和屬性;
◆ 副本數(shù)在建表時(shí)指定,后續(xù)無(wú)法修改;
◆ 表名和列名必須為有效的UTF-8字符串,最大256字符,且不支持其他編碼類(lèi)型;
◆ 刪除部分?jǐn)?shù)據(jù)不會(huì)立刻釋放存儲(chǔ)空間,必須等待KUDU內(nèi)部執(zhí)行Compaction后才會(huì)釋放,但如果刪除整張表,存儲(chǔ)空間會(huì)立即釋放。
總之,HDFS,HBase, KUDU都是優(yōu)秀的Hadoop技術(shù)組件,各有優(yōu)勢(shì)也都還存在不完美之處。具體使用什么組件存儲(chǔ)數(shù)據(jù)最合適,還是需要根據(jù)業(yè)務(wù)場(chǎng)景來(lái)確定。