細述hbase協處理器

1.原由(Why HBase Coprocessor)java

HBase做爲列族數據庫最常常被人詬病的特性包括:沒法輕易創建「二級索引」,難以執行求和、計數、排序等操做。好比,在舊版本的(<0.92)Hbase中,統計數據表的總行數,須要使用Counter方法,執行一次MapReduce Job才能獲得。雖然HBase在數據存儲層中集成了MapReduce,可以有效用於數據表的分佈式計算。然而在不少狀況下,作一些簡單的相加或者聚合計算的時候,若是直接將計算過程放置在server端,可以減小通信開銷,從而得到很好的性能提高。因而,HBase在0.92以後引入了協處理器(coprocessors),實現一些激動人心的新特性:可以輕易創建二次索引、複雜過濾器(謂詞下推)以及訪問控制等。sql

2.靈感來源( Source of Inspration)數據庫

HBase協處理器的靈感來自於Jeff Dean 09年的演講( P66-67)。它根據該演講實現了相似於bigtable的協處理器,包括如下特性:apache

每一個表服務器的任意子表均可以運行代碼 編程

客戶端的高層調用接口(客戶端可以直接訪問數據表的行地址,多行讀寫會自動分片成多個並行的RPC調用) 服務器

提供一個很是靈活的、可用於創建分佈式服務的數據模型 架構

可以自動化擴展、負載均衡、應用請求路由 併發

HBase的協處理器靈感來自bigtable,可是實現細節不盡相同。HBase創建了一個框架,它爲用戶提供類庫和運行時環境,使得他們的代碼可以在HBase region server和master上處理。負載均衡

3.細節剖析(Implementation)框架

協處理器分兩種類型,系統協處理器能夠全局導入region server上的全部數據表,表協處理器便是用戶能夠指定一張表使用協處理器。協處理器框架爲了更好支持其行爲的靈活性,提供了兩個不一樣方面的插件。一個是觀察者(observer),相似於關係數據庫的觸發器。另外一個是終端(endpoint),動態的終端有點像存儲過程。3.1觀察者(Observer)

觀察者的設計意圖是容許用戶經過插入代碼來重載協處理器框架的upcall方法,而具體的事件觸發的callback方法由HBase的核心代碼來執行。協處理器框架處理全部的callback調用細節,協處理器自身只須要插入添加或者改變的功能。

以HBase0.92版本爲例,它提供了三種觀察者接口:

RegionObserver:提供客戶端的數據操縱事件鉤子:Get、Put、Delete、Scan等。 

WALObserver:提供WAL相關操做鉤子。 

MasterObserver:提供DDL-類型的操做鉤子。如建立、刪除、修改數據表等。 

這些接口能夠同時使用在同一個地方,按照不一樣優先級順序執行.用戶能夠任意基於協處理器實現複雜的HBase功能層。HBase有不少種事件能夠觸發觀察者方法,這些事件與方法從HBase0.92版本起,都會集成在HBase API中。不過這些API可能會因爲各類緣由有所改動,不一樣版本的接口改動比較大,具體參考Java Doc。

RegionObserver工做原理,如圖1所示。更多關於Observer細節請參見HBaseBook的第 9.6.3章節。 

 

 

 

 

 3.2終端(Endpoint)

終端是動態RPC插件的接口,它的實現代碼被安裝在服務器端,從而可以經過HBase RPC喚醒。客戶端類庫提供了很是方便的方法來調用這些動態接口,它們能夠在任意時候調用一個終端,它們的實現代碼會被目標region遠程執行,結果會返回到終端。用戶能夠結合使用這些強大的插件接口,爲HBase添加全新的特性。終端的使用,以下面流程所示:

  1. 定義一個新的protocol接口,必須繼承CoprocessorProtocol.
  2. 實現終端接口,該實現會被導入region環境執行。
  3. 繼承抽象類BaseEndpointCoprocessor.
  4. 在客戶端,終端能夠被兩個新的HBase Client API調用 。
單個region:HTableInterface.coprocessorProxy(Class protocol, byte[] 
row) 。
rigons區域:HTableInterface.coprocessorExec(Class protocol, 
byte[] startKey, byte[] endKey, Batch.Call callable)

總體的終端調用過程範例,所示: 

 

 

 

 

4.編程實踐(Code Example)

在該實例中,咱們經過計算HBase表中行數的一個實例,來真實感覺協處理器 的方便和強大。在舊版的HBase咱們須要編寫MapReduce代碼來彙總數據表中的行數,在0.92以上的版本HBase中,只須要編寫客戶端的代碼便可實現,很是適合用在WebService的封裝上。

4.1啓用協處理器 Aggregation(Enable Coprocessor Aggregation)

咱們有兩個方法: 

1.啓動全局aggregation,能過操縱全部的表上的數據。經過修改hbase-site.xml這個文件來實現,只須要添加以下代碼:

<property>
 <name>hbase.coprocessor.user.region.classes</name>
 <value>org.apache.hadoop.hbase.coprocessor.AggregateImplementation</value>
</property>

2.啓用表aggregation,只對特定的表生效。經過HBase Shell 來實現。

  1. disable指定表。hbase> disable 'mytable'
  2. 添加aggregation hbase> alter 'mytable', METHOD => 
  3. 'table_att','coprocessor'=>'|org.apache.hadoop.hbase.coprocessor.AggregateImplementation||'
  4. 重啓指定表 hbase> enable 'mytable'
disable 'xyz'
alter 'xyz','coprocessor'=>'|org.apache.hadoop.hbase.coprocessor.example.RowCountEndpoint||'
enable 'xyz'

 

 

 

 

 

package hbase.learn.com;
import java.util.Map;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.client.HTable;
public class RowCount {
  public static void main(String[] args) {
   String tableName="xyz";
    // Get instance of Configuration
   Configuration configuration = HBaseConfiguration.create();
    // Get table instance
   HTable table = new HTable(configuration, tableName);
    final ExampleProtos.CountRequest request = ExampleProtos.CountRequest.getDefaultInstance();
     Map<byte[],Long> results = table.coprocessorService(ExampleProtos.RowCountService.class,
        null, null,
        new Batch.Call<ExampleProtos.RowCountService,Long>() {
         public Long call(ExampleProtos.RowCountService counter) throws IOException {
         ServerRpcController controller = new ServerRpcController();
         BlockingRpcCallback<ExampleProtos.CountResponse> rpcCallback =
            new BlockingRpcCallback<ExampleProtos.CountResponse>();
         counter.getRowCount(controller, request, rpcCallback);
         ExampleProtos.CountResponse response = rpcCallback.get();
          if (controller.failedOnException()) {
           throw controller.getFailedOn();
         }
          return (response != null && response.hasCount()) ? response.getCount() : 0;
        }
       });
      long sum=0;
      int count=0;
      for(Long l:results.values()){
       sum+=l;
       count++;
     }
     System.out.println("row count = "+sum);
     System.out.println("region count = "+count);
 }
}

 

 

歡迎工做一到五年的Java工程師朋友們加入Java架構開發: 855835163

羣內提供免費的Java架構學習資料(裏面有高可用、高併發、高性能及分佈式、Jvm性能調優、Spring源碼,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多個知識點的架構資料)合理利用本身每一分每一秒的時間來學習提高本身,不要再用"沒有時間「來掩飾本身思想上的懶惰!趁年輕,使勁拼,給將來的本身一個交代!

相關文章
相關標籤/搜索