分布式存儲(chǔ)系統(tǒng)Kudu與HBase的分析與對(duì)比
1 背景
Cloudera 在 2016 年發(fā)布了新型的分布式存儲(chǔ)系統(tǒng)—— kudu,kudu 目前也是 apache 下面的開源項(xiàng)目。Hadoop 生態(tài)圈中的技術(shù)繁多,HDFS 作為底層數(shù)據(jù)存儲(chǔ)的地位一直很牢固。而 HBase 作為 Google BigTable 的開源產(chǎn)品,一直也是 Hadoop 生態(tài)圈中的核心組件,其數(shù)據(jù)存儲(chǔ)的底層采用了 HDFS,主要解決的是在超大數(shù)據(jù)集場(chǎng)景下的隨機(jī)讀寫和更新的問題。Kudu 的設(shè)計(jì)有參考 HBase 的結(jié)構(gòu),也能夠?qū)崿F(xiàn) HBase 擅長的快速的隨機(jī)讀寫、更新功能。
那么同為分布式存儲(chǔ)系統(tǒng),HBase 和 Kudu 二者有何差異??jī)烧叩亩ㄎ皇欠裣嗤?/p>
接下來,土哥通過分析 HBase 與 Kudu 整體結(jié)構(gòu)和存儲(chǔ)結(jié)構(gòu)等方面對(duì)兩者的差異進(jìn)行比較。
2 整體結(jié)構(gòu)
2.1 HBase的整體結(jié)構(gòu)
圖片
HBase的主要組件包括 Master,zookeeper 服務(wù),RegionServer,HDFS。
Master:用來管理與監(jiān)控所有的HRegionServer,也是管理HBase元數(shù)據(jù)的模塊。
zookeeper:作為分布式協(xié)調(diào)服務(wù),用于保存meta表的位置,master的位置,存儲(chǔ)RS當(dāng)前的工作狀態(tài)。
RegionServer:負(fù)責(zé)維護(hù)Master分配的region,region對(duì)應(yīng)著表中一段區(qū)間內(nèi)的內(nèi)容,直接接受客戶端傳來的讀寫請(qǐng)求。
HDFS:負(fù)責(zé)最終將寫入的數(shù)據(jù)持久化,并通過多副本復(fù)制實(shí)現(xiàn)數(shù)據(jù)的高可靠性。
2.2 Kudu的整體結(jié)構(gòu)
圖片
Kudu 集群中存在兩種主要組件:
(1)TServer,負(fù)責(zé)管理Tablet,tablet是負(fù)責(zé)一張表中某塊內(nèi)容的讀寫,接收其他TServer中l(wèi)eader tablet傳來的同步信息。
(2)Master,集群中的管理節(jié)點(diǎn),用于管理tablet的基本信息,表的信息,并監(jiān)聽TServer的狀態(tài)。多個(gè)Master之間通過Raft協(xié)議實(shí)現(xiàn)數(shù)據(jù)同步和高可用。
2.3 主要區(qū)別
Kudu結(jié)構(gòu)看上去跟HBase差別并不大,主要的區(qū)別包括:
- Kudu將HBase中zookeeper的功能放進(jìn)了Master內(nèi),Kudu中Master的功能比HBase中的Master任務(wù)要多一些。
- Hbase將數(shù)據(jù)持久化這部分的功能交給了Hadoop中的HDFS,最終組織的數(shù)據(jù)存儲(chǔ)在HDFS上。Kudu 自己將存儲(chǔ)模塊集成在自己的結(jié)構(gòu)中,內(nèi)部的數(shù)據(jù)存儲(chǔ)模塊通過 Raft 協(xié)議來保證 leader Tablet 和 replica Tablet 內(nèi)數(shù)據(jù)的強(qiáng)一致性,和數(shù)據(jù)的高可靠性。為什么不像 HBase 一樣,利用 HDFS 來實(shí)現(xiàn)數(shù)據(jù)存儲(chǔ),猜測(cè)可能是因?yàn)?HDFS 讀小文件時(shí)的時(shí)延太大,所以 Kudu 自己重新完成了底層的數(shù)據(jù)存儲(chǔ)模塊,并將其集成在 TServer 中。
3 數(shù)據(jù)存儲(chǔ)方式
3.1 HBase
HBase是一款Nosql數(shù)據(jù)庫,典型的KV系統(tǒng),沒有固定的schema模式,建表時(shí)只需指定一個(gè)或多個(gè)列族名即可,一個(gè)列族下面可以增加任意個(gè)列限定名。一個(gè)列限定名代表了實(shí)際中的一列,HBase將同一個(gè)列族下面的所有列存儲(chǔ)在一起,所以HBase是一種面向列族式的數(shù)據(jù)庫。
圖片
HBase 將每個(gè)列族中的數(shù)據(jù)分別存儲(chǔ),一個(gè)列族中的每行數(shù)據(jù)中,將 rowkey、列族名、列名、timestamp 組成最終存取的key值,另外為了支持修改,刪除,增加了一個(gè)表征該行數(shù)據(jù)是否刪除的標(biāo)記。
在同一個(gè)列族中的所有數(shù)據(jù),按照 rowkey:columnfamily:columnQulifier:timestamp 組成的 key 值大小進(jìn)行升序排列,其中 rowkey、columnfamily、columnQulifier 采用的是字典順序,其值越大,key 越大,而 timestamp 是值越大,key 越小。HBase 通過按照列族分開存儲(chǔ),相對(duì)于行式存儲(chǔ)能夠?qū)崿F(xiàn)更高的壓縮比,這也是其比較重要的一個(gè)特性。
HBase 對(duì)一行數(shù)據(jù)進(jìn)行更新時(shí),HBase也是相當(dāng)于插入一行新數(shù)據(jù),在讀數(shù)據(jù)時(shí)HBase按照 timestamp 的大小得到經(jīng)過更新過的最新數(shù)據(jù)。
圖片
3.2 Kudu
Kudu是一種完全的列式存儲(chǔ)引擎,表中的每一列數(shù)據(jù)都是存放在一起,列與列之間都是分開的。
圖片
為了能夠保存一部分歷史數(shù)據(jù),并實(shí)現(xiàn) MVCC,Kudu 將數(shù)據(jù)分為三個(gè)部分。
- 第一部分叫做 base data,是當(dāng)前的數(shù)據(jù);
- 第二個(gè)部分叫做 UNDO records,存儲(chǔ)的是從插入數(shù)據(jù)時(shí)到形成 base data 所進(jìn)行的所有修改操作,修改操作以一定形式進(jìn)行組織,實(shí)現(xiàn)快速查看歷史數(shù)據(jù);
- 第三個(gè)部分是 REDO records,存儲(chǔ)的是還未 merge 到當(dāng)前數(shù)據(jù)中的更新操作。下圖中表示的是在 Kudu 中插入一條數(shù)據(jù)、更新數(shù)據(jù)兩個(gè)操作的做法,當(dāng)然做法不唯一,不唯一的原因是Kudu可以選擇先不將更新操作合并到 base data 中。
圖片
3.3 差異分析
(1)HBase 是面向列族式的存儲(chǔ),每個(gè)列族都是分別存放的,HBase 表設(shè)計(jì)時(shí),很少使用設(shè)計(jì)多個(gè)列族,大多情況下是一個(gè)列族。這個(gè)時(shí)候的 HBase 的存儲(chǔ)結(jié)構(gòu)已經(jīng)與行式存儲(chǔ)無太大差別了。而 Kudu,實(shí)現(xiàn)的是一個(gè)真正的面向列的存儲(chǔ)方式,表中的每一列都是單獨(dú)存放的;所以 HBase 與 Kudu 的差異主要在于類似于行式存儲(chǔ)的列族式存儲(chǔ)方式與典型的面向列式的存儲(chǔ)方式的差異。
(2)HBase 是一款 NoSQL 類型的數(shù)據(jù)庫,對(duì)表的設(shè)計(jì)主要在于 rowkey 與列族的設(shè)計(jì),列的類型可以不指定,因?yàn)?HBase 在實(shí)際存儲(chǔ)中都會(huì)將所有的 value 字段轉(zhuǎn)換成二進(jìn)制的字節(jié)流。因?yàn)椴恍枰付愋?,所以在插入?shù)據(jù)的時(shí)候可以任意指定列名(列限定名),這樣相當(dāng)于可以在建表之后動(dòng)態(tài)改變表的結(jié)構(gòu)。
Kudu 因?yàn)檫x擇了列式存儲(chǔ),為了更好的提高列式存儲(chǔ)的效果,Kudu 要求在建表時(shí)指定每一列的類型,這樣的做法是為了根據(jù)每一列的類型設(shè)置合適的編碼方式,實(shí)現(xiàn)更高的數(shù)據(jù)壓縮比,進(jìn)而降低數(shù)據(jù)讀入時(shí)的 IO 壓力。
(3)HBase 對(duì)每一個(gè) cell 數(shù)據(jù)中加入了 timestamp 字段,這樣能夠?qū)崿F(xiàn)記錄同一 rowkey 和列名的多版本數(shù)據(jù),另外 HBase 將數(shù)據(jù)更新操作、刪除操作也是作為一條數(shù)據(jù)寫入,通過 timestamp 來標(biāo)記更新時(shí)間,type 來區(qū)分?jǐn)?shù)據(jù)是插入、更新還是刪除。HBase 寫入或者更新數(shù)據(jù)時(shí)可以指定 timestamp,這樣的設(shè)置可以完成某些特定的操作。
Kudu 也在數(shù)據(jù)存儲(chǔ)中加入了 timestamp 這個(gè)字段,不像 HBase 可以直接在插入或者更新數(shù)據(jù)時(shí)設(shè)置特殊的 timestamp 值,Kudu 的做法是由 Kudu 內(nèi)部來控制timestamp 的寫入。不過 Kudu 允許在 scan 的時(shí)候設(shè)置 timestamp 參數(shù),使得客戶端可以 scan 到歷史數(shù)據(jù)。
(4)相對(duì)于 HBase 允許多版本的數(shù)據(jù)存在,Kudu 為了提高批量讀取數(shù)據(jù)時(shí)的效率,要求設(shè)計(jì)表時(shí)提供一列或者多列組成一個(gè)主鍵,主鍵唯一,不允許多個(gè)相同主鍵的數(shù)據(jù)存在。這樣的設(shè)置下,Kudu 不能像 HBase 一樣將更新操作直接轉(zhuǎn)換成插入一條新版本的數(shù)據(jù),Kudu 的選擇是將寫入的數(shù)據(jù),更新操作分開存儲(chǔ)。
(5)當(dāng)然還有一些其他的行式存儲(chǔ)與列式存儲(chǔ)之間在不同應(yīng)用場(chǎng)景下的性能差異。
4 總結(jié)
這里主要對(duì) Kudu和 HBase 在整體結(jié)構(gòu),數(shù)據(jù)存儲(chǔ)結(jié)構(gòu)方面進(jìn)行分析和比較。
Kudu 通過完整的表結(jié)構(gòu)設(shè)置,主鍵的設(shè)定,以列式存儲(chǔ)作為數(shù)據(jù)在磁盤上的組織方式,更新和數(shù)據(jù)分開等技巧,使得 Kudu 能夠?qū)崿F(xiàn)像HBase一樣實(shí)現(xiàn)數(shù)據(jù)的隨機(jī)讀寫之外,在 HBas不太擅長的批量數(shù)據(jù)掃描(scan)具有較好的性能。