Kudu的技術(shù)原理分析及與HBase的比較
2015.10 Jason
1????? kudu的設(shè)計(jì)初衷
在介紹Kudu是什么之前,還是先簡單的說一下現(xiàn)存系統(tǒng)針對結(jié)構(gòu)化數(shù)據(jù)存儲的一些痛點(diǎn)問題。結(jié)構(gòu)化數(shù)據(jù)的存儲,通常包含如下兩種方式:
l? 靜態(tài)數(shù)據(jù)通常以Parquet或者Avro形式直接存放在HDFS中,對于分析場景,這種存儲通常是更加適合的。但無論以哪種方式存在于HDFS中,都難以支持單條記錄級別的更新,隨機(jī)讀取也并不高效。
l? 可變數(shù)據(jù)的存儲通常選擇HBase或者Cassandra,因?yàn)樗鼈兡軌蛑С钟涗浖墑e的高效讀寫。但這種存儲卻并不適合分析場景,因?yàn)樗鼈冊诖髷?shù)據(jù)量順序讀取場景下的性能相對較差(針對HBase而言,有兩方面的主要原因。一是HFile本身的結(jié)構(gòu)定義,它是按行組織數(shù)據(jù)的,這種格式針對大多數(shù)的分析場景,都會帶來較大的IO消耗,因?yàn)榭赡軙x取很多不必要的數(shù)據(jù),相對而言Parquet格式針對分析場景就做了很多優(yōu)化。 二是由于HBase本身的LSM-Tree架構(gòu)決定的,HBase的讀取路徑中,不僅要考慮內(nèi)存中的數(shù)據(jù),同時(shí)要考慮HDFS中的一個(gè)或多個(gè)HFile,較之于直接從HDFS中讀取文件而言,這種路徑是過長的)。
可以看出,如上兩種存儲方式,都存在明顯的優(yōu)缺點(diǎn)。 直接存放于HDFS中,盡管適合分析,但卻不利于記錄級別的隨機(jī)讀寫。而直接將數(shù)據(jù)存放于HBase中,適合記錄級別的隨機(jī)讀寫,但卻并不適合分析。 而在很多業(yè)務(wù)場景中,我們都可能同時(shí)存在這兩類場景。我們的通常做法有如下幾種:
1. 數(shù)據(jù)存放于HBase中,對于分析任務(wù),基于Hive Over HBase/MapReduce進(jìn)行。可容忍這種場景下的分析性能。
2. 對于分析性能要求較高的,可以將數(shù)據(jù)在HDFS/Hive中多冗余存放一份。或者將HBase中的數(shù)據(jù)定期的導(dǎo)出成Parquet格式的數(shù)據(jù)。 明顯的,這種方案中,數(shù)據(jù)一致性是一個(gè)較大的問題。同時(shí),架構(gòu)也較復(fù)雜。
圖表 1 Kudu在生態(tài)系統(tǒng)中的定位
Kudu的設(shè)計(jì),就是試圖在實(shí)時(shí)分析與隨機(jī)讀寫之間,尋求一個(gè)最佳的結(jié)合。另外一個(gè)初衷,在Cloudera發(fā)布的《Kudu: New Apache Hadoop Storage for Fast Analytics on Fast Data》一文中有提及,Kudu作為一個(gè)新的分布式存儲系統(tǒng)也是為了進(jìn)一步提升CPU的適用效率。下面的章節(jié)中,將會詳細(xì)介紹Kudu的設(shè)計(jì)原理。
2????? Kudu的原理介紹
2.1????? 表與Schema
Kudu設(shè)計(jì)是面向結(jié)構(gòu)化存儲的,因此,Kudu的表,需要用戶在建表時(shí)定義它的Schema信息,這些Schema信息包含:列定義(含類型),Primary Key定義(用戶指定的若干個(gè)列的有序組合)。數(shù)據(jù)的唯一性,依賴于用戶所提供的Primary Key中的Column組合的值的唯一性。 Kudu提供了Alter命令來增刪列,但位于Primary Key中的列是不允許刪除的。
Kudu當(dāng)前并不支持二級索引。
2.2????? API
Kudu提供了Java/C++兩種語言的API(盡管也提供了Python API,但尚處于Experimental階段)。通過這些API,可以進(jìn)行如下一些操作:
l? Insert/Update/Delete
l? 批量數(shù)據(jù)導(dǎo)入/更新操作
l? Scan(可支持簡單的Filter)
l? …………
2.3????? 事務(wù)與一致性模型
Kudu僅僅提供單行事務(wù),也不支持多行事務(wù)。這一點(diǎn)與HBase是相似的。但在數(shù)據(jù)一致性模型上,與HBase有較大的區(qū)別。 Kudu提供了如下兩種一致性模型:
l? Snapshot Consistency
這是Kudu中的默認(rèn)一致性模型。在這種模型中,只保證一個(gè)客戶端能夠看到自己所提交的寫操作,而并不保障全局的(跨多個(gè)客戶端的)事務(wù)可見性。
l? External Consistency
最早提出External Consistency機(jī)制的,應(yīng)該是在Google的Spanner論文中。傳統(tǒng)關(guān)系型數(shù)據(jù)庫中的兩階段提交機(jī)制,需要兩回合通信,這過程中帶來的代價(jià)是較高的,但同時(shí)這過程中的復(fù)雜的鎖機(jī)制也可能會帶來一些可用性問題。一個(gè)更好的實(shí)現(xiàn)分布式事務(wù)/一致性的思路,是基于一個(gè)全局發(fā)布的Timestamp機(jī)制。Spanner提出了Commit-wait的機(jī)制,來保障全局事務(wù)的有序性:如果一個(gè)事務(wù)T1的提交先于另外一個(gè)事務(wù)T2的開始,則T1的Timestamp要小于T2的TimeStamp。我們知道,在分布式系統(tǒng)中,是很難于做這樣的承諾的。在HBase中,我們可以想象,如果所有RegionServer中的SequenceID發(fā)布自同一個(gè)數(shù)據(jù)源,那么,HBase的很多事務(wù)性問題就迎刃而解了,然后最大的問題在于這個(gè)全局的SequenceID數(shù)據(jù)源將會是整個(gè)系統(tǒng)的性能瓶頸點(diǎn)。回到External Consistency機(jī)制,Spanner是依賴于高精度與可預(yù)見誤差的本地時(shí)鐘(TrueTime API)實(shí)現(xiàn)的(即需要一個(gè)高可靠和高精度的時(shí)鐘源,同時(shí),這個(gè)時(shí)鐘的誤差是可預(yù)見的。感興趣的同學(xué)可以閱讀Spanner論文,這里不贅述)。Kudu中提供了另外一種思路來實(shí)現(xiàn)External Consistency,基于Timestamp擴(kuò)散機(jī)制,即,多個(gè)客戶端可相互通信來告知彼此所提交的Timestamp值,從而保障一個(gè)全局的順序。這種機(jī)制也是相對較為復(fù)雜的。
與Spanner類似,Kudu不允許用戶自定義用戶數(shù)據(jù)的Timestamp,但在HBase中卻是不同。用戶可以發(fā)起一次基于某特定Timestamp的查詢。
2.4????? Kudu的架構(gòu)
Kudu也采用了Master-Slave形式的中心節(jié)點(diǎn)架構(gòu),管理節(jié)點(diǎn)被稱作Kudu Master,數(shù)據(jù)節(jié)點(diǎn)被稱作Tablet Server(可對比理解HBase中的RegionServer角色)。一個(gè)表的數(shù)據(jù),被分割成1個(gè)或多個(gè)Tablet,Tablet被部署在Tablet Server來提供數(shù)據(jù)讀寫服務(wù)。
Kudu Master在Kudu集群中,發(fā)揮如下的一些作用:
1.???? 用來存放一些表的Schema信息,且負(fù)責(zé)處理建表等請求。
2.???? 跟蹤管理集群中的所有的Tablet Server,并且在Tablet Server異常之后協(xié)調(diào)數(shù)據(jù)的重部署。
3.???? 存放Tablet到Tablet Server的部署信息。
Tablet與HBase中的Region大致相似,但存在如下一些明顯的區(qū)別點(diǎn):
1.???? Tablet包含兩種分區(qū)策略,一種是基于Hash Partition方式,在這種分區(qū)方式下用戶數(shù)據(jù)可較均勻的分布在各個(gè)Tablet中,但原來的數(shù)據(jù)排序特點(diǎn)已被打亂。另外一種是基于Range Partition方式,數(shù)據(jù)將按照用戶數(shù)據(jù)指定的有序的Primary Key Columns的組合String的順序進(jìn)行分區(qū)。而HBase中僅僅提供了一種按用戶數(shù)據(jù)RowKey的Range Partition方式。
2.???? 一個(gè)Tablet被部署到了多個(gè)Tablet Server中。然而,在HBase最初的架構(gòu)中,一個(gè)Region卻是被部署在了一個(gè)RegionServer中,它的數(shù)據(jù)多副本是交由HDFS來保障的。盡管后來HBase有了Region Replica特性,或者是Facebook貢獻(xiàn)的HydraBase的設(shè)計(jì)思路來實(shí)現(xiàn)Region的多個(gè)副本,來優(yōu)化HBase的MTTR時(shí)間,但迄今為止均尚不成熟。
圖表 2 Kudu的數(shù)據(jù)多副本機(jī)制
圖表 3 HBase的數(shù)據(jù)多副本機(jī)制
2.5????? Kudu的底層數(shù)據(jù)模型
Kudu的底層數(shù)據(jù)文件的存儲,未采用HDFS這樣的較高抽象層次的分布式文件系統(tǒng),而是自行開發(fā)了一套可基于Table/Tablet/Replica視圖級別的底層存儲系統(tǒng)。這套實(shí)現(xiàn)基于如下的幾個(gè)設(shè)計(jì)目標(biāo):
l? 可提供快速的列式查詢。
l? 可支持快速的隨機(jī)更新
l? 可提供更為穩(wěn)定的查詢性能保障。
為了實(shí)現(xiàn)如上目標(biāo),Kudu參考了一種類似于Fractured Mirrors的混合列存儲架構(gòu)。Tablet在底層被進(jìn)一步細(xì)分成了一個(gè)稱之為RowSets的單元:
圖表 4 RowSets
MemRowSets可以對比理解成HBase中的MemStore, 而DiskRowSets可理解成HBase中的HFile。MemRowSets中的數(shù)據(jù)按照行試圖進(jìn)行存儲,數(shù)據(jù)結(jié)構(gòu)為B-Tree。MemRowSets中的數(shù)據(jù)被Flush到磁盤之后,形成DiskRowSets。 DisRowSets中的數(shù)據(jù),按照32MB大小為單位,按序劃分為一個(gè)個(gè)的DiskRowSet。
DiskRowSet中的數(shù)據(jù)按照Column進(jìn)行組織,與Parquet類似。這是Kudu可支持一些分析性查詢的基礎(chǔ)。每一個(gè)Column的數(shù)據(jù)被存儲在一個(gè)相鄰的數(shù)據(jù)區(qū)域,而這個(gè)數(shù)據(jù)區(qū)域進(jìn)一步被細(xì)分成一個(gè)個(gè)的小的Page單元,與HBase File中的Block類似,對每一個(gè)Column Page可采用一些Encoding算法,以及一些通用的Compression算法。
既然可對Column Page可采用Encoding以及Compression算法,那么,對單條記錄的更改就會比較困難了。前面提到了Kudu可支持單條記錄級別的更新/刪除,是如何做到的?與HBase類似,也是通過增加一條新的記錄來描述這次更新/刪除操作的。一個(gè)DiskRowSet包含兩部分?jǐn)?shù)據(jù):基礎(chǔ)數(shù)據(jù)(Base Data),以及變更數(shù)據(jù)(Delta Stores)。更新/刪除操作所生成的數(shù)據(jù)記錄,被保存在變更數(shù)據(jù)部分。
圖表 5 Delta Store Design
上圖來自Kudu的源工程文件。 從上圖來看,Delta數(shù)據(jù)部分應(yīng)該包含REDO與UNDO兩部分,這里的REDO與UNDO與關(guān)系型數(shù)據(jù)庫中的REDO與UNDO日志類似(在關(guān)系型數(shù)據(jù)庫中,REDO日志記錄了更新后的數(shù)據(jù),可以用來恢復(fù)尚未寫入Data File的已成功事務(wù)更新的數(shù)據(jù)。 而UNDO日志用來記錄事務(wù)更新之前的數(shù)據(jù),可以用來在事務(wù)失敗時(shí)進(jìn)行回滾),但也存在一些細(xì)節(jié)上的差異。如下是源碼中關(guān)于REDO與UNDO的解釋:
REDO Delta Files包含了Base Data自上一次被Flush/Compaction之后的變更值。REDO Delta Files按照Timestamp順序排列。
UNDO Delta Files包含了Base Data自上一次Flush/Compaction之前的變更值。這樣才可以保障基于一個(gè)舊Timestamp的查詢能夠看到一個(gè)一致性視圖。 UNDO按照Timestamp倒序排列。
2.6????? 數(shù)據(jù)讀寫流程
寫數(shù)據(jù)的流程,如下圖所示:
圖表 6 Write Path
Kudu不允許用戶數(shù)據(jù)的Primary Key重復(fù),因此,在Tablet內(nèi)部寫入數(shù)據(jù)之前,需要先從已有的數(shù)據(jù)中檢查當(dāng)前新寫入的數(shù)據(jù)的Primary Key是否已經(jīng)存在,盡管在DiskRowSets中增加了BloomFilter來提升這種判斷的效率,但可以預(yù)見,Kudu的這種設(shè)計(jì)將會明顯增大寫入的時(shí)延。
數(shù)據(jù)一開始先存放于MemRowSets中,待大小超出一定的閾值之后,再Flush成DiskRowSets。這部分已經(jīng)在圖表5中有詳細(xì)的介紹。隨著Flush次數(shù)的不斷增加,生成的DiskRowSets也會不斷的增多,在Kudu內(nèi)部也存在一個(gè)Compaction流程,這樣可以將已經(jīng)存在的多個(gè)存在Primary Key交集的DiskRowSets重新排序而生成一個(gè)新的DiskRowSets。如下圖所示:
圖表 7 RowSet Compaction
讀數(shù)據(jù)的流程,既要考慮存在于內(nèi)存中的MemRowSets,又要讀取位于磁盤中的一個(gè)或多個(gè)DiskRowSets,在Scanner的高層抽象中,應(yīng)該與HBase類似。如下重點(diǎn)提一些細(xì)節(jié)的優(yōu)化點(diǎn):
1.???? 通過Scan的范圍,與每一個(gè)DiskRowSets中的Primary Key Range進(jìn)行對比,可以首先過濾掉一些不必要參與此次Scan的DiskRowSets。
2.???? Delta Store部分,針對記錄級別的更改,記錄了Base Data中對應(yīng)原始數(shù)據(jù)的Offset。這樣,在判斷一條記錄是否存在更改的記錄時(shí),將會更加的快速。
3.???? 由于DiskRowSets的底層文件是按照列組織的,基于一些列的條件進(jìn)行過濾查詢時(shí),可以優(yōu)先過濾掉一些不必要的Primary Keys。Kudu并不會在一開始讀取的時(shí)候就將一行數(shù)據(jù)的所有列讀取出來,而是先讀取與過濾條件相關(guān)的列,通過將這些列與查詢條件匹配之后,再來決定是否去讀取符合條件的行中的其它的列信息。這樣可以節(jié)省一些磁盤IO。這就是Kudu所提供的Lazy Materialization特性。
2.7????? Raft模型
與HydraBase類似,Kudu采用了Raft協(xié)議,來保持Tablet多副本之間的數(shù)據(jù)一致性。Raft是比Paxos更容易理解且更簡單的一種一致性協(xié)議,請參考:https://raft.github.io/。 Paxos更多的是從理論上提供了一種一致性模型,而Raft確實(shí)一種更貼近實(shí)際應(yīng)用的實(shí)現(xiàn)。
3????? Kudu與HBase的區(qū)別
這里再總結(jié)一下Kudu與HBase的一些大的區(qū)別點(diǎn):
l? Kudu的數(shù)據(jù)分區(qū)方式相對多樣化,而HBase較單一。
l? Kudu的Tablet自身具備多副本機(jī)制,而HBase的Region依賴于底層HDFS的多副本機(jī)制。在HBase 1.0版本中已經(jīng)有了Region Replica(HBASE-10070)特性,同時(shí),社區(qū)還有Facebook貢獻(xiàn)的HydraBase的方案,但均尚不成熟。
l? Kudu底層不依賴于其它的分布式文件系統(tǒng)。而HBase依賴于HDFS。
l? Kudu的底層文件格式采用了類似于Parquet的列式存儲格式,而HBase的底層HFile文件卻是按行來組織的。
l? Kudu關(guān)于底層的Flush任務(wù)以及Compaction任務(wù),能夠結(jié)合忙時(shí)或者閑時(shí)進(jìn)行自動的調(diào)整。HBase還尚不具備這種調(diào)度能力。
l? Kudu的Compaction無Minor/Major的區(qū)分,限制每一次Compaction的IO總量在128MB大小,因此,并不存在長久執(zhí)行的Compaction任務(wù)。 Compaction是按需進(jìn)行的,例如,如果所有的寫入都是順序?qū)懭耄瑒t將不會觸發(fā)Compaction。
l? Kudu的設(shè)計(jì),既兼顧了分析型的查詢能力,又兼顧了隨機(jī)讀寫能力,這樣,勢必也會付出一些代價(jià)。 例如,寫入數(shù)據(jù)時(shí)關(guān)于Primary Key唯一性的限制,就要求寫入前要檢查對應(yīng)的Primary Key是否已經(jīng)存在,這樣勢必會增大寫入的時(shí)延。而底層盡管采用了類似于Parquet的列式文件設(shè)計(jì),但與HBase類似的冗長的讀取路徑,也會對分析性的查詢帶來一些影響。另外,這種設(shè)計(jì)在整行讀取時(shí),也會付出較高的代價(jià)。
4????? Kudu與現(xiàn)有系統(tǒng)的對接
Kudu提供了與如下一些系統(tǒng)的對接:
l? MapReduce: 提供針對Kudu用戶表的Input以及Output任務(wù)對接。
l? Spark: 提供與Spark SQL以及DataFrames的對接。
l? Impala: Kudu自身未提供Shell以及SQL Parser,所以,它的SQL能力源自與Impala的集成。在這些集成中,能夠很好的感知Kudu表數(shù)據(jù)的本地性信息,能夠充分利用Kudu所提供的過濾器對查詢進(jìn)行優(yōu)化,同時(shí),Impala本身的DDL/DML語法針對Kudu也做了一些擴(kuò)展。可以想象,Cloudera在Impala與Kudu的集成上,未來一定會有更多的發(fā)力點(diǎn)。
5????? Kudu的適用場景
Todd Lipcon在今年的Strata+Hadoop World 2015大會上所提供的主題為《Kudu: Resolving transactional and analytic trade-offs in Hadoop》的演講中,這樣子描述Kudu的適用場景:
6????? Kudu Benchmark數(shù)據(jù)解析
如下使得Kudu WhitePage中所提供的一些Benchmark性能測試數(shù)據(jù)的簡單解析(詳細(xì)的結(jié)果請參考論文的第6章節(jié)):
1.???? 基于TPC-H測試標(biāo)準(zhǔn),針對Impala On Parquet以及Impala On Kudu做了對比測試,Impala On Kudu的平均性能比Impala On Parquet提升了31%。這是由于Kudu所提供的Lazy Meterialization特性以及對對CPU效率的提升而帶來的成果。
2.???? Impala-Kudu與Phoenix-HBase的對比:
測試使用到了TPC-H中的lineitem一表,共導(dǎo)入了62GB的CSV格式的數(shù)據(jù)。在導(dǎo)入Phoenix時(shí)使用了Phoenix所提供的CsvBulkLoadTool工具。測試時(shí)的一些配置信息如下所示:
l? 為Phoenix表劃分了100個(gè)Hash Partitions。為Kudu創(chuàng)建了100個(gè)Tablets。
l? HBase采用默認(rèn)的Block Cache策略,為每一個(gè)RegionServer配置了9.6GB的Cache內(nèi)存。而Kudu配置了1GB的Block Cache的進(jìn)程內(nèi)存,但同時(shí)還依賴于操作系統(tǒng)的Buffer。
l? HBase表中采用了FAST_DIFF的Block Encoding算法,未啟用任何壓縮。
數(shù)據(jù)導(dǎo)入到HBase中之后,主動觸發(fā)了一次Major Compaction,來確保數(shù)據(jù)的本地化率。62GB原始數(shù)據(jù)導(dǎo)入到HBase中之后的總大小約為570GB(這是由于未啟用Compression壓縮,同時(shí),由于多個(gè)列都是獨(dú)立存在的帶來的膨脹導(dǎo)致),而導(dǎo)入到Kudu中之后的大小約為227GB。如下是相應(yīng)的對比測試場景以及對比結(jié)果:
除了基于Key值的整行數(shù)據(jù)的查詢性能,Phoenix有明顯的優(yōu)勢以外,其它的基于整表掃描,或者是基于一些列的查詢,Impala-Kudu是有明顯的優(yōu)勢的。基于Scan + Filter的查詢,HBase本身就不擅長。
3.???? 隨機(jī)讀寫能力的對比
如下是對比測試的一些場景:
如下是對比測試的結(jié)果:
關(guān)于加載以及Zipfian分布模式下,HBase的優(yōu)勢更加明顯,當(dāng)前Kudu也正在做關(guān)于Zipfian分布模式下的優(yōu)化(KUDU-749),而在Uniform模式下,HBase的優(yōu)勢稍弱。整體來看,在隨機(jī)讀寫上,Kudu的設(shè)計(jì)較之HBase而言,存在一些劣勢,這是為了兼顧分析型查詢所付出的一些代價(jià)。
7????? 參考信息
[1]http://blog.cloudera.com/blog/2015/09/kudu-new-apache-hadoop-storage-for-fast-analytics-on-fast-data/
[2] http://getkudu.io/kudu.pdf
[3] https://www.oreilly.com/ideas/kudu-resolving-transactional-and-analytic-trade-offs-in-hadoop
[4] https://dev.mysql.com/doc/refman/5.7/en/innodb-undo-logs.html
[5] https://raft.github.io/
[6]http://static.googleusercontent.com/media/research.google.com/zh-CN//archive/spanner-osdi2012.pdf
HBase 表格存儲服務(wù) CloudTable 智能數(shù)據(jù) EI企業(yè)智能
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。