一个自定义 HBase Filter -“通过RowKeys来高性能获取数据”
摘要: 大家在使用HBase和Solr搭建系統中經常遇到的一個問題就是:“我通過SOLR得到了RowKeys后,該怎樣去HBase上取數據”。使用現有的Filter性能差勁,網上也沒有現成的自定義Filter解決方案,我在這里把這個問題的解決辦法分享給大家,拋磚引玉一下。先講一下,雖然使用自定義過濾器來達到取數據的目的,但它其實并不是一個好的解決辦法,因為它的性能是有問題的,具體分析還要看我的博客HBase 高性能獲取數據 - 多線程批量式解決辦法:http://www.cnblogs.com/wgp13x/p/4245182.html
?
Solr和HBase專輯
1、“關于Solr的使用總結的心得體會”(http://www.cnblogs.com/wgp13x/p/3742653.html)
2、“中文分詞器性能比較?”(http://www.cnblogs.com/wgp13x/p/3748764.html)
3、“Solr與HBase架構設計”(http://www.cnblogs.com/wgp13x/p/a8bb8ccd469c96917652201007ad3c50.html)
4、?“大數據架構: 使用HBase和Solr將存儲與索引放在不同的機器上”(http://www.cnblogs.com/wgp13x/p/3927979.html)
5、“一個自定義 HBase Filter -通過RowKeys來高性能獲取數據”(http://www.cnblogs.com/wgp13x/p/4196466.html)
?
? ??? ? ?“大數據架構: 使用HBase和Solr將存儲與索引放在不同的機器上”此文一經推出,覽者眾多,也有很多同仁朋友問我問題,看來近年關注先進大數據架構的公司越來越多了,基本上有數據接入的公司都會有這一問題。具我所知,“我該選Oracle還是MySQL作數據存儲呢?”,“MySQL數據庫索引創建后對雙百分號%like不起作用啊!”,“沒事,數據量再大我加存儲柜不就行了?哈哈哈!”,這些都是還在用關系型數據庫存儲大數據的公司,它們往往對查詢這塊束手無策;它們的對策往往是:“我退而求其次,往年的數據我搜不了,我只搜今年的數據不就OK啦?反正業務單位我也能搞定。”--這是有壟斷有背景的公司,也是不思進取的公司,“我分表,用戶查近三個月的數據多,查前面的數據少,我每個月分一張表,解決了。”--這是吃了這頓沒下頓的公司,抓緊把當前的項目搞完拿錢走人的公司,“上內存數據庫哎,那個快。”--這是不管三七二十一、以屁股決定腦袋的公司。不管怎么說,能關注當前大數據架構技術的公司都是不落伍滴。 ? ? ??? 現在我把大家在使用HBase和Solr搭建系統中經常遇到的一個問題的解決辦法在這里分享給大家,這個問題就是:“我通過SOLR得到了RowKeys后,該怎樣去HBase上取數據”。 ? ? ??? 相信有人開始發問了,HBase不是提供了功能很強勁的Filter了嗎?Comparision Filters,Dedicated Filters,Decorating Filters,可以或可以且,可以相等,還可以組合,看起來很豐滿,用起來很骨感。經過一番實踐過后,性能低得嚇人,使用200條RowKey在300百萬的數據集中取數據,要等上好幾鐘,究其原因,多Filter的或組合過濾就是在HBase的數據里滾了一遍又一遍,不慢才怪。 ? ? ??? ??那么應該怎么做呢?自定義HBase Filter,這樣只要滾一遍就好啦。RowKeyFilter就是自定義的Filter,它繼承自FilterBase類,類中主要定義了三個屬性,byte[] value用來傳入RowKeys,Map<Object, Object>用來存放傳入的RowKeys,撞到了就返回,boolean filterRow用來告訴HBase是否濾掉。下面是具體的RowKeyFilter代碼。 ?
| import?java.io.DataInput; import?java.io.DataOutput; import?java.io.IOException; import?java.util.Arrays; import?java.util.HashMap; import?java.util.Map; import?org.apache.hadoop.hbase.KeyValue; import?org.apache.hadoop.hbase.filter.FilterBase; import?org.apache.hadoop.hbase.util.Bytes; /** ?*?@description?自定義過濾器,用來讀取大量離散行 ?*?@author?王安琪 ?*?@time?2014年11月8日上午10:47:17 ?*?@className?RowKeyFilter ?*/ public?class?RowKeyFilter?extends?FilterBase { ????private?byte[]?value?=?null; ????private?boolean?filterRow?=?true; ????/** ?????*?map中存放需要讀的行RowKey ?????*/ ????public?Map<Object,?Object>?map?=?new?HashMap<Object,?Object>(); ????public?RowKeyFilter() ????{ ????????super(); ????} ????public?RowKeyFilter(byte[]?value) ????{ ????????this.value?=?value; ????} ????@Override ????public?ReturnCode?filterKeyValue(KeyValue?ignored) ????{ ????????if?(this.filterRow?==?false) ????????????return?ReturnCode.INCLUDE; ????????else ????????????return?ReturnCode.NEXT_ROW; ????} ????/** ?????*?行過濾,查詢該行RowKey是否在Map中 ?????*/ ????@Override ????public?boolean?filterRowKey(byte[]?buffer,?int?offset,?int?length) ????{ ????????byte[]?rowKey?=?Arrays.copyOfRange(buffer,?offset,?offset?+?length); ????????String?str?=?new?String(rowKey); ????????if?(map.containsKey(str)) ????????{?//?在0(1)時間內返回,效率較高 ????????????this.filterRow?=?false;?//?false表示包括這一行 ????????} ????????return?this.filterRow; ????} ????@Override ????public?void?reset() ????{ ????????this.filterRow?=?true; ????} ????@Override ????public?boolean?filterRow() ????{ ????????return?filterRow; ????} ????/** ?????*?將Map中的數據以Byte[]形式傳給服務器 ?????*/ ????@Override ????public?void?write(DataOutput?dataOutput)?throws?IOException ????{ ????????Bytes.writeByteArray(dataOutput,?this.value); ????} ????/** ?????*?服務器讀取Byte[]數據,再將數據存儲到Map中?不同的RowKey以","分割 ?????*/ ????@Override ????public?void?readFields(DataInput?dataInput)?throws?IOException ????{ ????????this.value?=?Bytes.readByteArray(dataInput); ????????String?string?=?new?String(this.value); ????????String[]?strs?=?string.split(","); ????????for?(String?str?:?strs) ????????{ ????????????map.put(str,?str); ????????} ????} } |
| /** ?????*?根據rowKeys獲取數據 ?????*? ?????*?@param?rowKeys:每個rowkey之間使用逗號分隔符 ?????*?@param?filterColumn:表示過濾的列,如果為空表示所有列的數據都返回 ?????*?@param?isContiansRowkeys:設置為true,表示返回結果集中包含rowkeys;否則返回結果集中不包含rowkeys ?????*?@return ?????*/ ????/*?@Override?*/ ????public?Datas?getDatasFromHbase(String?rowKeys,?List<String>?filterColumn, ????????boolean?isContiansRowkeys) ????{ ????????Datas?datas?=?new?Datas(); ????????HTableInterface?hTableInterface?=?getTable(tableName); ????????Scan?scan?=?new?Scan(); ????????if?(filterColumn?!=?null) ????????{ ????????????for?(String?column?:?filterColumn) ????????????{ ????????????????scan.addColumn(columnFamilyName.getBytes(),?column.getBytes()); ????????????} ????????} ????????if?(rowKeys?!=?null?&&?rowKeys.length()?>?0) ????????{ ????????????RowKeyFilter?rowKeyFilter?=?new?RowKeyFilter(rowKeys.getBytes()); ? ? ? ? ? ??? ??? ??? ??scan.setFilter(rowKeyFilter); ????????} ????????ResultScanner?resultScanner?=?null; ????????List<Data>?listData?=?new?ArrayList<Data>(); ????????try ????????{ ????????????resultScanner?=?hTableInterface.getScanner(scan); ????????????for?(Result?result?:?resultScanner) ????????????{ ????????????????Data?data?=?new?Data(); ????????????????if?(isContiansRowkeys) ????????????????{ ????????????????????data.setRowkey(new?String(result.getRow())); ????????????????} ????????????????Map<String,?String>?map?=?new?HashMap<String,?String>(); ????????????????List<String>?content?=?new?ArrayList<String>(); ????????????????String[]?temp?=?null; ????????????????if?(filterColumn?!=?null) ????????????????{ ????????????????????temp?=?new?String[filterColumn.size()]; ????????????????} ????????????????for?(KeyValue?keyValue?:?result.raw()) ????????????????{ ????????????????????if?(filterColumn?==?null) ????????????????????{ ????????????????????????content.add(new?String(keyValue.getValue())); ????????????????????} ????????????????????else?if?(filterColumn?!=?null) ????????????????????{ ????????????????????????String?qualifier?=?new?String(keyValue.getQualifier()); ????????????????????????String?value?=?new?String(keyValue.getValue()); ????????????????????????if?(filterColumn.contains(qualifier)) ????????????????????????{ ????????????????????????????int?index?=?filterColumn.indexOf(qualifier); ????????????????????????????temp[index]?=?value; ????????????????????????} ????????????????????} ????????????????} ????????????????if?(temp?!=?null) ????????????????{ ????????????????????for?(int?i?=?0;?i?<?temp.length;?i++) ????????????????????{ ????????????????????????content.add(temp[i]); ????????????????????} ????????????????} ? ??? ??? ??? data.setContent(content); ????????????????listData.add(data); ????????????} ????????????datas.setDatas(listData); ????????} ????????catch?(IOException?e) ????????{ ????????????e.printStackTrace(); ????????} ????????finally ????????{ ????????????resultScanner.close(); ????????????try ????????????{ ????????????????hTableInterface.close(); ????????????} ????????????catch?(IOException?e) ????????????{ ????????????????e.printStackTrace(); ????????????} ????????} ????????return?datas; ????} |
轉載于:https://www.cnblogs.com/wgp13x/p/4196466.html
總結
以上是生活随笔為你收集整理的一个自定义 HBase Filter -“通过RowKeys来高性能获取数据”的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Socket的select制作多客户端传
- 下一篇: int转string的3种方法