Apache HBase 2015年發展回顧與未來展望
張虔熙,Hulu 網,專注于分布式存儲和計算,HBase contributor。
HBase 2015 年技術發展
在 2015 年,HBase 迎來了一個里程碑——HBase 1.0 release,這也代表著 HBase 走向了穩定。
New Interface(更加清晰的接口定義)
舊的 HBase 接口邏輯與傳統 JDBC 方式很不相同,新的接口與傳統 JDBC 的邏輯更加相像,具有更加清晰的 Connection 管理方式。同時,在舊的接口中,客戶端何時將 Put 寫到服務端也需要設置,一個 Put 馬上寫到服務端,還是攢到一批寫到服務端,新用戶往往對此不太清楚。在新的接口中,引入了 BufferedMutator,可以提供更加高效清晰的寫操作。
HBase 0.98 與 HBase 1.0 接口名稱對比
舉一個例子,舊的 API 寫入操作的代碼:
新的 API 寫入操作的代碼:
可以看到,在操作前,首先建立連接,然后拿到一個對應表的句柄,之后再進行一系列操作。以上兩個是同步寫操作。下面看一下批量異步寫入接口:
代碼有相應的注釋,可見新的接口顯得更加清晰。
多個 Region 副本(讀操作高可用 HBASE-10070)
如圖所示,在 HBase 中,Table 被橫向劃分為 Region,它是一段數據的管理者,Region 被分發到 RegionServer 上進行管理,一個 Region 只被一個 RegionServer 管理,它的數據存儲在 HDFS 上,是可以有多個副本的。
也就是說:管理者 (Region) 只有一個,數據有多個副本。
HBase 的以前實現中,當一臺 RegionServer 不可用時,需要數十秒甚至數分鐘才可以完成發現和恢復工作,在這段時間內,這臺 RegionServer 上的 Region 是不可用的。當一個 Region 不可用時,它需要一段時間才可以被其他 RegionServer 接管。
在最新的實現中,一個 Region 可以有多個副本(Region 是數據的管理者,是實際數據的抽象),分布在多個 RegionServer 上。
特點:
- 有一個主 Region,多個從 Region。
- 只有主 Region 接收寫請求,并把數據持久化到 HDFS 上。
- 從 Region 從 HDFS 中讀取數據并服務讀請求。
- 從 Region 可能會讀到臟數據(主 Region 內存中的數據)。
- 讀操作可以只讀主,或者既可以讀主又可讀從(可配置)。
這樣在主 Region 不可用時,用戶仍可以讀從 Region 的數據。目前社區在進行的開發:主 Region 異步同步數據到從 Region,從而減少從 Region 缺少的數據量。
Family 粒度的 Flush(減少小文件,優化磁盤 IO,提高讀性能 HBASE-10201)
我們先看一下 HBase 的寫流程圖
數據從客戶端寫到 RegionServer 上的 Region 后,先寫入到內存中,積攢到閾值后寫入磁盤,即 LSM-tree 架構。
在以前的實現中,服務端數據從內存刷寫到 HDFS 上是 Region 粒度的,Region 下面所有的 Family 都會被 Flush。在很多應用場景中,HBase 中存儲的是稀疏數據,在寫入一行的數據中,有的 Family 具有值,有的為空,而且不同 Family 中存儲的數據大小本身就不同,所以當大的 Family 到達閾值需要刷寫數據時,小的 Family 也會跟著刷寫,這樣會導致很多小文件的產生,影響性能。
在新的實現中,提供了更小粒度的 Flush——Family 級別。它的特點是:
- 更加合理的使用內存的寫延遲和聚合功能
- 減少 Compaction 的磁盤IO
- 提高讀性能
RPC 讀寫隊列分離(讀寫隔離,scan 與 get 隔離 HBASE-11355)
之前的實現中,RegionServer 上所有操作共享隊列,各種操作互相影響。比如Scan 和 Get,在 RPC Call Queue 中,如果一個大的 Scan 請求排列在 Get 之前,那么 Get 就需要等待之前的 Scan 完成才可以執行,延遲較大。
在現在的實現中,RPC 可以具有多個 Call Queue,同時將它們分配給不同的操作使用,從而實現各種 Put、Scan 和 Get 等操作的隔離。具體配置的參數如下:
hbase.ipc.server.callqueue.handler.factor
hbase.ipc.server.callqueue.read.ratio
hbase.ipc.server.callqueue.scan.ratio
在線調整配置 HBASE-12147
之前的實現中,每次修改配置后都需要重啟集群(Rolling Restart)
現在,調整配置后不再需要重啟,但是目前只支持一部分配置的在線調整,如 Load Balance 和 Compaction。Hadoop 也已經實現了此功能。
目前社區的工作方向和趨勢:
提高可用性
很多應用都要求存儲具有高可用性,目前 HBase 實現的還不夠優秀,非死book 的 HydraHBase 是 非死book 內部維護的 HBase 版本,它使用 Raft 協議管理 Region Server,從而實現高可靠,它的可用率達到 99.999%,非死book 聲稱 HydraBase 能將 非死book 全年的宕機時間縮減到不到 5 分鐘。Cloudera Kudu 使用 Raft 協議管理協調 Tablet,從而也可以達到很高的可用率。
HBase 與 HydraHBase 對比:
HBase
HydraBase
對于 HDFS 多存儲介質的使用
隨著 HDFS 對內存、SSD 的支持和使用,HBase 也會充分使用它們帶來的高性能。比如把 WAL 和更多的熱數據放到 HDFS 的內存或者 SSD上(三副本)
減少對 ZooKeeper 的使用
Zookeeper 的抖動會對 HBase 造成影響,目前已經完成對 Master 上的 Assignment Manager 的改造,使它不再依賴 ZooKeeper。
堆外內存的使用
Java 管理大內存的方式還不高效,HBase 可以把 Cache 放在堆外,讀取的時候不再拉到堆內中,以減少 GC 的影響。
Q & A
1、HBase 集群是不是盡量要讀寫分離(針對整個集群),我們的集群,隨機寫入很大,也有隨機讀,現在碰到隨機讀請求很不穩定的情況,希望有經驗分享一下
HBase 可以支持高吞吐的寫請求。對于隨機讀,如果寫操作很多,會造成很多文件來不及 Compact,這會影響隨機讀的性能。同時,如果 JVM 參數沒有經過調優,忙碌的 HBase 集群會有 GC 問題,也會影響隨機讀的性能。建議可以先調優 JVM 參數和 Cache,也可以引入 BloomFilter 等來優化查詢。如果對隨機讀延遲要求較高,可以考慮分離讀寫。
2、對于 HBASE 臟讀問題,如果只讀從 region,是不是就可以避免了?
不能,因為從 Region 的數據就是過時的,主 Region 才是最新的數據。目前 HBase 的實現中,只有讀主 Region 才可以獲得最新數據,當主 Region 不可用時,如果可以忍受 stale 的數據,則可以讀從 Region 來保證可用性。目前高可用實現的還不太好,這也是社區努力的方向之一。
3、修改 HBase 配置文件,但不重啟集群是怎么實現的?
Hadoop 實現了一個動態載入配置的框架,修改配置后,激發服務端重新獲取配置。具體可見 Hadoop-7001(https://issues.apache.org/jira/browse/HADOOP-7001)
4、HBase 歷史數據有好的處理辦法嗎?設定多少天之前的數據刪除或者只對對歷史數據進行壓縮?
可以設置 TTL 來淘汰歷史數據,設置的時間根據具體應用來定。HBase 可以支持 Family 級別設置壓縮,原生 HBase 還不能對于一部分行做壓縮,可以考慮分表或者其他上層實現。如果歷史數據不再需要,可以考慮設置 TTL。
5、寫 MapReduce job 從 HBase 中導出某張表的所有數據,默認是幾個 region 產生幾個 mapper,有什么可以優化提速的辦法?
可以讓多個 mapper 讀取一個 region 中的數據,這時候你需要定制一下 TableInputFormat(適當修改源代碼)
6、0.98 版本或以前的 HBase 有什么好的讀寫分離方案?snapshot 是不是是一種方法?
從 RPC 層面上講,snapshot 不算讀寫分離方案,因為所有的讀寫都進入同一個 Call Queue。從 MVCC 和鎖級別等其他方面來看,snapshot 是一種方案。
7、HBase multitenant 方面有解決方案沒有?
社區已經有相應的 issue,在明年發布的 2.0 版本中會發布。
8、HBase 不同集群之間的數據同步在 1.0 版本之后有沒有更好的解決方案?
目前的解決方案仍然是 copytable + replication。目前社區已經可以解決 bulk load 的數據的同步(之前 bulk load 的數據不能同步到從集群)。
9、基于 HBase 緩存怎么設計比較好,Hulu 是怎么做的?我的項目里用了 Cloudera 自帶的 Solr,發現服務器 memory CPU 開銷太大。
HBase 的隨機讀性能不足為在線服務提供緩存服務,可以考慮使用 Redis 或者 Memcache。Solr 應該是做全文索引服務,這應該和 Solr 的實現相關。如果沒有設置把 HBase 的表放到內存,HBase 不會消耗很大內存。對于忙碌的 HBase 集群,還是比較消耗 CPU 。
10、社區版 Hadoop 2.6 沒有對應的 HBase 版本支持,可以用剛才講的 HydraBase 替代 HBase 嗎?
HBase 1.0 應該是可以運行在 Hadoop 2.6 之上,從個人角度來看,HydraBase可以替代 HBase,非死book 就是這么實現的,不過 HydraBase 還沒有開源。從架構上來講,HydraBase 使用 Raft 協議管理 RegionServer,寫性能可能不如原生 HBase。
11、請問你們是否在生產環境種使用 HBase + Phoenix 的組合來提供復雜快速查詢?如果使用了,并發查詢的性能如何?
Hulu 內部還沒有使用 Phoenix,以前我個人使用過 Phoenix,當時 Phoenix 對于大量并發查詢支持的不好,尤其是使用了索引的復雜查詢。但是 Phoenix 社區發展很快,現在的情況應該會有好轉。
12、Off-heap 做二級 cache 能否提高隨機讀速度?
可以 。 bucket cache 實現的比較好。目前社區仍在繼續優化。對于隨機讀,還可以增加 BloomFilter 增強性能。
13、HBase 的 Rowkey 如何設計才能既保持無熱點又能有序便于 scan?
可以考慮 salt 的方式,在寫入的時候為 Rowkey 加隨機前綴,比如前綴范圍 001 – 100,那么我可以隨機為 Rowkey 加上這些前綴來消除熱點,在 scan 的時候需要加上所有的前綴(001-100)來 scan,不過這樣一個 scan 就要轉化為并發的 100 個 scan。
轉載請注明出處:代碼說 ? Apache HBase 2015年發展回顧與未來展望