1. 程式人生 > >關於HBase協處理器導致問題的研究

關於HBase協處理器導致問題的研究

1 載入協處理器
1.1 將協處理器上傳到hdfs:
hadoop fs -mkdir /hbasenew/usercoprocesser
hadoop fs -ls /hbasenew/usercoprocesser
hadoop fs -rm /hbasenew/usercoprocesser/coprocessor.jar
hadoop fs -copyFromLocal /home/hbase/coprocessor.jar  /hbasenew/usercoprocessor
1.2 將協處理器載入到表中:
1)先解除安裝協處理器:
disable 'ns_bigdata:tb_test_coprocesser'
alter 'ns_bigdata:tb_test_coprocesser',METHOD => 'table_att_unset',NAME =>'coprocessor$1'
enable 'ns_bigdata:tb_test_coprocesser'
2)再載入協處理器:
disable 'ns_bigdata:tb_test_coprocesser'
alter 'ns_bigdata:tb_test_coprocesser',METHOD => 'table_att','coprocessor' => '/hbasenew/usercoprocesser/coprocessor.jar|com.suning.hbase.coprocessor.service.HelloWorldEndPoin|1001|'
enable 'ns_bigdata:tb_test_coprocesser'
注意:在載入協處理器是我特意將協處理器中的類名少寫一個字母t,以重現將叢集regionserver搞掛的現象以及表的狀態不一致的現象。

2 出現的問題
以上操作會導致如下兩個問題:
2.1 將叢集的region server搞掛掉

2.2 將載入協處理器的表的狀態搞的不一致,一直處於enabling狀態

對錶做disable和enable操作均不可操作:

同時此表對應的regionserver上出現如下錯誤:

3 原因分析
3.1 關於協處理載入錯誤導致regionserver掛掉的原因分析
在hbase的原始碼中,引數:hbase.coprocessor.abortonerror的預設值是true:
public static final String ABORT_ON_ERROR_KEY = "hbase.coprocessor.abortonerror";
  public static final boolean DEFAULT_ABORT_ON_ERROR = true;
下面檢視此引數的含義:
<property>
      <name>hbase.coprocessor.abortonerror</name>
      <value>true</value>
      <description>Set to true to cause the hosting server (master or regionserver)
      to abort if a coprocessor fails to load, fails to initialize, or throws an
      unexpected Throwable object. Setting this to false will allow the server to
      continue execution but the system wide state of the coprocessor in question
      will become inconsistent as it will be properly executing in only a subset
      of servers, so this is most useful for debugging only.</description> </property>
因此,當載入錯誤的協處理器之後,會導致regionserver掛掉。

3.2 關於載入協處理器的表的狀態不一致的原因分析:
相關錯誤日誌:

檢視enable的相關原始碼:
public void enableTable(final TableName tableName)
  throws IOException {
    enableTableAsync(tableName);

    // Wait until all regions are enabled
    waitUntilTableIsEnabled(tableName);

    LOG.info("Enabled table " + tableName);
  }
private void waitUntilTableIsEnabled(final TableName tableName) throws IOException {
    boolean enabled = false;
    long start = EnvironmentEdgeManager.currentTimeMillis();
    for (int tries = 0; tries < (this.numRetries * this.retryLongerMultiplier); tries++) {
      try {
        enabled = isTableEnabled(tableName);
      } catch (TableNotFoundException tnfe) {
        // wait for table to be created
        enabled = false;
      }
      enabled = enabled && isTableAvailable(tableName);
      if (enabled) {
        break;
      }
      long sleep = getPauseTime(tries);
      if (LOG.isDebugEnabled()) {
        LOG.debug("Sleeping= " + sleep + "ms, waiting for all regions to be " +
          "enabled in " + tableName);
      }
      try {
        Thread.sleep(sleep);
      } catch (InterruptedException e) {
        // Do this conversion rather than let it out because do not want to
        // change the method signature.
        throw (InterruptedIOException)new InterruptedIOException("Interrupted").initCause(e);
      }
    }
    if (!enabled) {
      long msec = EnvironmentEdgeManager.currentTimeMillis() - start;
      throw new IOException("Table '" + tableName +
        "' not yet enabled, after " + msec + "ms.");
    }
  }

===========================================================================
  /**
   * Brings a table on-line (enables it).  Method returns immediately though
   * enable of table may take some time to complete, especially if the table
   * is large (All regions are opened as part of enabling process).  Check
   * {@link #isTableEnabled(byte[])} to learn when table is fully online.  If
   * table is taking too long to online, check server logs.
   * @param tableName
   * @throws IOException
   * @since 0.90.0
   */
  public void enableTableAsync(final TableName tableName)
  throws IOException {
    TableName.isLegalFullyQualifiedTableName(tableName.getName());
    executeCallable(new MasterCallable<Void>(getConnection()) {
      @Override
      public Void call() throws ServiceException {
        LOG.info("Started enable of " + tableName);
        EnableTableRequest req = RequestConverter.buildEnableTableRequest(tableName);
        master.enableTable(null,req);
        return null;
      }
    });
  }
發現在enable的過程中,首先是執行enable操作,操作完畢後需要等待各個regionserver反饋所有region的狀態,由於此時regionserver已經掛掉,一直在連線重試等待,此時表的狀態一直是ENABLING。

4 問題的處理
4.1 關於regionserver 掛掉的問題處理:
通過在hbase-site.xml檔案中設定引數:
    <property>
    <name>hbase.coprocessor.abortonerror</name>
    <value>false</value>
    </property>
並啟動region server可以解決,這樣就忽略了協處理器出現的錯誤,保證叢集高可用。
4.2 關於有協處理器的表的狀態不一致,不能disable和enable問題的解決辦法:
此問題可以通過切換master節點可以解決,將主停掉,backup-master會承擔主master的任務,同時在切換的過程中,會將狀態不一致的表的狀態改為一致的:

 切換後的master資訊如下:

在切換的過程中呼叫瞭如下方法:
  /**
   * Recover the tables that are not fully moved to ENABLED state. These tables
   * are in ENABLING state when the master restarted/switched
   *
   * @throws KeeperException
   * @throws org.apache.hadoop.hbase.TableNotFoundException
   * @throws IOException
   */
  private void recoverTableInEnablingState()
      throws KeeperException, TableNotFoundException, IOException {
    Set<TableName> enablingTables = ZKTable.getEnablingTables(watcher);
    if (enablingTables.size() != 0) {
      for (TableName tableName : enablingTables) {
        // Recover by calling EnableTableHandler
        LOG.info("The table " + tableName
            + " is in ENABLING state.  Hence recovering by moving the table"
            + " to ENABLED state.");
        // enableTable in sync way during master startup,
        // no need to invoke coprocessor
        EnableTableHandler eth = new EnableTableHandler(this.server, tableName,
          catalogTracker, this, tableLockManager, true);
        try {
          eth.prepare();
        } catch (TableNotFoundException e) {
          LOG.warn("Table " + tableName + " not found in hbase:meta to recover.");
          continue;
        }
        eth.process();
      }
    }
  }
在卻換過程中,跟蹤master和對應的regionserver的後臺日誌:
master日誌:
其中的部分日誌資訊如下:
2015-05-20 10:00:01,398 INFO  [master:nim-pre:60000] master.AssignmentManager: The table ns_bigdata:tb_test_coprocesser is in ENABLING state.  Hence recovering by moving the table to ENABLED state.
2015-05-20 10:00:01,421 DEBUG [master:nim-pre:60000] lock.ZKInterProcessLockBase: Acquired a lock for /hbasen/table-lock/ns_bigdata:tb_test_coprocesser/write-master:600000000000002
2015-05-20 10:00:01,436 INFO  [master:nim-pre:60000] handler.EnableTableHandler: Attempting to enable the table ns_bigdata:tb_test_coprocesser
2015-05-20 10:00:01,465 INFO  [master:nim-pre:60000] handler.EnableTableHandler: Table 'ns_bigdata:tb_test_coprocesser' has 1 regions, of which 1 are offline.
2015-05-20 10:00:01,466 INFO  [master:nim-pre:60000] balancer.BaseLoadBalancer: Reassigned 1 regions. 1 retained the pre-restart assignment. 
2015-05-20 10:00:01,466 INFO  [master:nim-pre:60000] handler.EnableTableHandler: Bulk assigning 1 region(s) across 3 server(s), retainAssignment=true
對應的regionserver的日誌如下:
2015-05-20 14:39:56,175 INFO  [master:sup02-pre:60000] master.AssignmentManager: The table ns_bigdata:tb_test_coprocesser is in ENABLING state.  Hence recovering by moving the table to ENABLED state.
2015-05-20 14:39:56,211 DEBUG [master:sup02-pre:60000] lock.ZKInterProcessLockBase: Acquired a lock for /hbasen/table-lock/ns_bigdata:tb_test_coprocesser/write-master:600000000000031
2015-05-20 14:39:56,235 INFO  [master:sup02-pre:60000] handler.EnableTableHandler: Attempting to enable the table ns_bigdata:tb_test_coprocesser
2015-05-20 14:39:56,269 INFO  [master:sup02-pre:60000] handler.EnableTableHandler: Table 'ns_bigdata:tb_test_coprocesser' has 1 regions, of which 1 are offline.
2015-05-20 14:39:56,270 INFO  [master:sup02-pre:60000] balancer.BaseLoadBalancer: Reassigned 1 regions. 1 retained the pre-restart assignment. 
2015-05-20 14:39:56,270 INFO  [master:sup02-pre:60000] handler.EnableTableHandler: Bulk assigning 1 region(s) across 3 server(s), retainAssignment=true

結論:
1. 為了提高叢集的高可用性,應該將引數:hbase.coprocessor.abortonerror設定為false,這樣即使載入的協處理器有問題,也不會導致叢集的regionserver掛掉,也不會導致表不能enable和disable;
2.即使表出現不能enable和disable的現象後,也可以通過切換master來解決,因此在搭建叢集時,一定要至少有一到兩個backupmaster

5 全部master節點宕後集群的讀寫測試
1. 在叢集都是正常的情況下,通過客戶端往叢集中插入2000000行資料,插入正常
2.將叢集的所有master全部停掉:

3.監控客戶端的資料插入情況,發現客戶端的資料插入正常。持續讓客戶端繼續插入20000000行資料,發現數據插入正常。
4.在客戶端批量讀取資料,發現數據讀取正常。
結論:當hbase叢集的master所有節點掛掉後(一定時間段,目前測試的是半小時內),客戶端的資料讀寫正常。

zz:http://blog.csdn.net/dcswinner/article/details/46293041

相關推薦

關於HBase處理器導致問題的研究

1 載入協處理器 1.1 將協處理器上傳到hdfs: hadoop fs -mkdir /hbasenew/usercoprocesser hadoop fs -ls /hbasenew/usercoprocesser hadoop fs -rm /hbasenew/us

HBase處理器

協處理器分兩種型別,系統協處理器可以全域性匯入region server上的所有資料表,表協處理器即是使用者可以指定一張表使用協處理器。協處理器框架為了更好支援其行為的靈活性,提供了兩個不同方面的外掛。一個是觀察者(observer),類似於關係資料庫的觸發器。另一個是終端(endpoint),

hbase處理器與二級索引

一、協處理器—Coprocessor 1、 起源 Hbase 作為列族資料庫最經常被人詬病的特性包括:無法輕易建立“二級索引”,難以執 行求和、計數、排序等操作。比如,在舊版本的(<0.92)Hbase 中,統計資料表的總行數,需 要使用 Counte

HBase處理器載入過程(1.2.x)

一、首先來看ObserverCoprocessor:1.觀察者協處理器的靜態載入的配置是在hbase-site.xml中配置如下屬性:通過hbase.coprocessor.region.classes 配置 RegionObservers 和 Endpoints.通過hb

HBae找不到處理器導致RegionServer全部掛掉

一、問題背景:     跟兄弟單位公用一個大資料叢集,通過Dataspace結合Kerberos控制資料的訪問,我們生產環境中用到的OLAP工具Kylin,在升級Kylin的過程中,由於刪除了舊的協處理器,導致原來資料繼續去尋找目標協處理器,找不到引起所有RegionS

HBase處理器載入過程(1.2)

之前寫過HBase協處理器的一些原理和使用,基本上都是官方文件和官方的部落格翻過來的,知道了怎麼寫,怎麼用。 現在需要思考的一個問題是,自己寫的協處理器是怎麼載入成功並呼叫的。 一、首先來看ObserverCoprocessor: 1.觀察者協處理器的靜態載入的配置是在hb

HBase-6.hbase 處理器

引入Hbase中的Coprocessor的原因HBase作為列族資料庫無法建立“二級索引”,難以執行求和、計數、排序等操作。為解決這些問題,HBase0.92 之後引入協處理器(Coprocessor),實現一些新特性,能夠輕易建立二次索引、複雜過濾器、以及訪問控制。參考: http://blog.csdn.

HBase 處理器實踐(一)AggregationClient

                                                                                                    

hbase處理器簡介

本章要點 hbase協處理器有哪幾種類型 hbase協處理器如何部署 協處理器的主要介面,已經介面功能 自定義協處理器例項 協處理器型別 hbase協處理型別主要分為observer 和endpoint兩種型別。 observer

hbase處理器--建立endpoint處理器

下載hbase-source之後,裡面有相應的原始碼,可以找到RowCountEndpoint.java,ExampleProto.java等一系列程式碼。通過閱讀原始碼以及其中的註釋,我們可以知道,Hbase的很多的功能都是通過protobuf這個工具來生成程式碼,尤其是

HBase處理器同步二級索引到Solr

一、 已知的問題和不足    在上一個版本中,實現了使用HBase的協處理器將HBase的二級索引同步到Solr中,但是仍舊有幾個缺陷:寫入Solr的Collection是寫死在程式碼裡面,且是唯一的。如果我們有一張表的資料希望將不同的欄位同步到Solr中該如何做呢?目前所有

HBase 處理器 (二)

3.7 The RegionObserver Class 用於 region level, 注意,這個類的所有呼叫方法的第一個引數為 ObserverContext<RegionCoprocessorEnvironment> ctx8, 提供訪問 conte

HBase 處理器統計行數

環境:cdh5.1.0 啟用協處理器方法1. 啟用協處理器 Aggregation(Enable Coprocessor Aggregation) 我們有兩個方法:1.啟動全域性aggregatio

HBase 系列(八)——HBase 處理器

一、簡述 在使用 HBase 時,如果你的資料量達到了數十億行或數百萬列,此時能否在查詢中返回大量資料將受制於網路的頻寬,即便網路狀況允許,但是客戶端的計算處理也未必能夠滿足要求。在這種情況下,協處理器(Coprocessors)應運而生。它允許你將業務計算程式碼放入在 RegionServer 的協處理器中

HBase處理器

HBase中的協處理器有兩種:observer和endpoint Observer coprocessor:類似於RDBMS中的觸發器,它在特定事件(例如Get或Put)發生之前或之後執行你的程式碼。 Endpoint coprocessor:類似於RDBMS中的儲存過程,它允許你在Re

HBase利用observer(處理器)建立二級索引

一、協處理器—Coprocessor         1、 起源 Hbase 作為列族資料庫最經常被人詬病的特性包括:無法輕易建立“二級索引”,難以執 行求和、計數、排序等操作。比如,在舊版本的(<0.92)Hbase 中,統

Hbase Coprocessor(處理器)的使用

本部落格記錄初次使用hbase coprocessor的過程。協處理器分兩種型別,系統協處理器可以全域性匯入region server上的所有資料表,表協處理器即是使用者可以指定一張表使用協處理器。協處理器框架為了更好支援其行為的靈活性,提供了兩個不同方面的外掛

使用HBase Coprocessor處理器

原文: HBase的Coprocessor是模仿谷歌BigTable的Coprocessor模型實現的。 Coprocessor提供了一種機制可以讓開發者直接在RegionServer上執行自定義程式碼來管理資料。 首先必須要指明使用Coproc

使用處理器HBase資料索引到Elasticsearch叢集

HBaseCon 2013: Using Coprocessors to Index Columns in an Elasticsearch Cluster 使用協處理器將列資料索引到Elasticsearch叢集     總結來說,一般就是擴充套件RegionObs

HBase學習之三: hbase filter(過濾器)和coprocessor(處理器)統計行數的簡單應用

2.通過coprocessor統計行數   關於協處理器的介紹和用法網上很多資料,可以自行查詢腦補,值得注意的是協處理器在hbase伺服器端執行,開發者可自定義處理器放置於伺服器端然後再客戶端呼叫,