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