HBase多條件及分頁查詢的一些方法

HBase是Apache Hadoop生態系統中的重要一員,它的海量數據存儲能力,超高的數據讀寫性能,以及優秀的可擴展性使之成爲最受歡迎的NoSQL數據庫之一。它超強的插入和讀取性能與它的數據組織方式有着密切的關係,在邏輯上,HBase的表數據按RowKey進行字典排序, RowKey其實是數據表的一級索引(Primary Index),因爲HBase自己沒有二級索引(Secondary Index)機制,基於索引檢索數據只能單純地依靠RowKey。也只有使用RowKey查詢數據才能獲得很是高的效率。固然,HBase也支持使用其餘的字段進行查詢,可是隻要沒有RowKey,那麼都是全表掃描。試想一下,在數十億數據中全表掃描是一種什麼樣的體驗,查詢幾乎不可用。而做爲數據庫使用,在數據表上的多條件查詢是必然的需求,本文將結合使用經驗,介紹一些常規的HBase的多條件查詢實現方式。數據庫

 

RowKey + Filter的方式緩存

RowKey通常是必不可少的,可是若是數據量少,幾十萬數據,就問題不大。不少時候查詢都會選擇時間,若是能把時間放在RowKey裏面,會極大的提高查詢的效率。這裏有個小技巧:若是Rowkey是按時間戳的方式遞增,不要將時間放在二進制碼的前面,建議將Rowkey的高位做爲散列字段,由程序循環生成,低位放時間字段,這樣將提升數據均衡分佈在每一個Regionserver實現負載均衡的概率。若是沒有散列字段,首字段直接是時間信息將產生全部新數據都在一個RegionServer上堆積的熱點現象,這樣在作數據檢索的時候負載將會集中在個別RegionServer,下降查詢效率。架構

HBase的Scan能夠經過setFilter方法添加過濾器(Filter),這也是分頁、多條件查詢的基礎。HBase爲篩選數據提供了一組過濾器,經過這個過濾器能夠在HBase中的數據的多個維度(行,列,數據版本)上進行對數據的篩選操做。一般來講,經過行鍵,值來篩選數據的應用場景較多。這裏簡單舉個例子,使用SingleColumnValueFilter過濾行,查找數據庫中vehicle_speed列是77的數據:負載均衡

FilterList filterList = new FilterList();
SingleColumnValueFilter scvf = new SingleColumnValueFilter(Bytes.toBytes("f"), Bytes.toBytes("vehicle_speed"), CompareOp.EQUAL, Bytes.toBytes("77"));
filterList.addFilter(scvf);
scan.setFilter(filterList);
ResultScanner scanner = table.getScanner(scan);

Filter是能夠加多個的,HBase提供十多種Filter類型。filterList.addFilter(scvf) 就是能夠添加多個查詢條件,而後調用setFilter函數給Scanner。異步

這裏再簡單介紹一下分頁的方式:分佈式

  • client分頁,scan查到N*M條,過濾掉N*M-M條,返回M條。對於M,N較小時比較適合。
  • 自定義Filter,該filter能夠傳遞offset(server端須要過濾的記錄條數),在server端分頁,注意,跨不一樣的region時須要從新計算該offset
  • 緩存上次分頁查詢的最後一條,下次分頁查詢從這條(不包含)開始查。
  • 查詢條件固定的話,定時任務彙總表
  • PageFilter

使用RowKey + Filter的方式只能知足一些查詢(數據量少,或者RowKey是必須的參數),包括其分頁的實現並非最優,但這是使用原生的HBase的方法,比較簡單。下面介紹的方法更好,可是依賴於其餘的組件。函數

 

Coprocessor工具

利用Coprocessor協處理器,用戶能夠編寫運行在 HBase Server 端的代碼。HBase的Coprocessor分爲兩類,Observer和EndPoint。oop

HBase 支持兩種類型的協處理器,Endpoint 和 Observer。Endpoint 協處理器相似傳統數據庫中的存儲過程,客戶端能夠調用這些 Endpoint 協處理器執行一段Server 端代碼,並將 Server 端代碼的結果返回給客戶端進一步處理。post

另一種協處理器叫作Observer Coprocessor,這種協處理器相似於傳統數據庫中的觸發器,當發生某些事件的時候這類協處理器會被 Server 端調用。Observer Coprocessor 就是一些散佈在 HBase Server 端代碼中的 hook 鉤子,在固定的事件發生時被調用。好比:put 操做以前有鉤子函數 prePut,該函數在 put 操做執行前會被 Region Server 調用;在 put 操做以後則有 postPut 鉤子函數。

使用Coprocessor來實現簡單的HBase二級索引也是比較常見的方案。可是若是要使用Coprocessor進行二級索引的話,仍是推薦下面成熟的方案,它其中也使用到了協處理器。

 

Phoenix

最先由Salesforce.com開源的Apache Phoenix 是一個Java中間層,可讓開發者在Apache HBase上執行SQL查詢,目前的版本基本支持經常使用的操做(分頁,排序,Group By,Having,函數,序列等等)。目前的Phoenix是很是成熟的解決方案,阿里、Salesforce、eBay等互聯網都在普遍使用。

Phoenix徹底使用Java編寫,代碼位於GitHub上,而且提供了一個客戶端可嵌入的JDBC驅動。它查詢的實時性很是高,通常查詢都在秒級返回,能夠應用OLTP的系統中。在用戶必須經過Phoenix來建HBase的表,它會映射到HBase的表上。Phoenix能夠建立索引來提高提高多條件查詢HBase的效率。好比,在查詢訂單的時候,能夠經過訂單號、時間、狀態等不一樣的維度來查詢,要想把這麼多角度的數據都放到RowKey中幾乎不可能。而在Phoenix中,你能夠針對這幾個字段創建索引。在寫SQL語句的時候,若是Where語句中使用到了這些條件,Phoenix就會自動判斷是否走索引。

Phoenix的索引本質上也是一張HBase的表,它維護了索引和RowKey的關係。在查詢的時候,它會從索引表中先找到RowKey,而後再根據RowKey再去HBase原始數據表中獲取數據。關於Phoenix的二級索引在後續的文章中專門介紹。

 

Impala

Impala是Cloudera在受到Google的Dremel啓發下開發的實時交互SQL大數據查詢工具,Impala沒有再使用緩慢的Hive+MapReduce批處理,而是經過使用與商用並行關係數據庫中相似的分佈式查詢引擎(由Query Planner、Query Coordinator和Query Exec Engine三部分組成),能夠直接從HDFS或HBase中用SELECT、JOIN和統計函數查詢數據,從而大大下降了延遲。

Impala目前是Apache的孵化項目。Impala並不是是一個OLTP系統,而更像是一個OLAP系統,更加相似於Hive。Impala不能運用在實時系統中,可是若是是針對HBase的統計或者異步查詢的話不妨一試。

 

ElasticSearch/Solr + HBase

針對HBase使用RowKey訪問超高的效率,咱們能夠把索引數據放在相似於ElasticSearch或者Solr這樣的搜索引擎裏面。用搜索引擎作二級索引。查詢數據的時候先從搜索引擎中查詢出RowKey,而後再用RowKey去獲取數據。流行的搜索引擎基本能夠知足查詢的全部需求。

舉個例子:訂單數據項有10個,可是用於查詢的有5個。當數據插入HBase的同時,也把這5個數據項加上預先生成的RowKey插入搜索引擎,也就是說部分數據存儲兩份。一份用於搜索,一份用於查詢。大體的架構也許會是這樣:

image

程序A和B分開主要是爲了解耦和避免互相影響,固然也能夠合併在一個程序裏面。程序A和B也能夠是相似於flume或者logstash這樣的組件。

 

一些建議

在做者的實際經驗中方案的選擇仍是要根據數據量和性能要求來選擇。當數據量較小几十萬,上百萬的話可使用RowKey+Filter的方式實現。若是數據量到了千萬,甚至億級別,能夠嘗試Phoenix。若是數據量到了10億或者更多則須要選擇搜索引擎。同時方案的系統維護難度和對技術的要求也是逐級遞增的。

相關文章
相關標籤/搜索