HBase運維 | HBase宕機恢復案例一則

快下班的時候突然收到zk、HBase宕機的告警,瞬間一萬匹草泥馬奔騰而過,但是問題終究得解決啊,搞起來。

下圖爲master的日誌記錄:

從上圖可以看到zk中/Hbase/replication/rs的節點信息無法獲取,然後我們立馬去檢查zk日誌發現zk已經全部斷聯而且已經癱瘓,截圖如下:

上網一番查找發現java.nio.channels.CancelledKeyException是zk 3.4.10之前版本的bug,筆者使用的正是3.4.8,此bug在3.4.10已修復。

至此,zk宕機原因找到了,將zk節點全部重啓然後重啓HBase,核心問題來了,遇到了一個老兄弟,java.io.IOException: Packet len6075380 is out of range ! master退出,啓動失敗。

按照以前的經驗,去zkCli.sh修改了-Djute.maxbuffer=41943040的配置,第一次修改直接將值翻倍後重啓還是報同樣的錯誤,多次翻倍終無效果;一氣之下直接將值多加了兩個00,變成了之前的上千倍,數值達到了百億級別,重啓依然無效。然後決定刪除zk中的HBase節點,rmr /habse竟然報錯了,更巧的是同樣的java.io.IOException: Packet len6075380 is out of range ! 好難受啊!!!

折騰了這麼半天沒有思路了,突然運維的同事提醒我說我改的值應該已經超出zk的限制了,估計都不會生效,聽了這麼一個提醒,心裏竊喜的很啊,馬上一番操作下載zk源碼看看到底怎麼回事。

void readLength() throws IOException {
    int len = incomingBuffer.getInt();
    if (len < 0 || len >= packetLen) {
        throw new IOException("Packet len" + len + " is out of range!");
    }
    incomingBuffer = ByteBuffer.allocate(len);
}

packetLen爲配置文件的值,而incomingBuffer爲HBase啓動報錯的值:6075380 > 4194304(默認值),所以拋出上述異常:

private int packetLen = ZKClientConfig.CLIENT_MAX_PACKET_LENGTH_DEFAULT;

查看源碼發現zk初始化的時候會去加載配置文件的·jute.maxbuffer·值,如果值的大小不爲空就採用此值,如果爲空就用默認值,上圖紅色部分爲默認是大小4M=4194304,但還有一個前提就是配置的值必須是int範圍內的值,否則Integer.parseInt(value.trim())方法會報錯。

    try {
        packetLen = clientConfig.getInt(ZKConfig.JUTE_MAXBUFFER,
                ZKClientConfig.CLIENT_MAX_PACKET_LENGTH_DEFAULT);
        LOG.info("{} value is {} Bytes", ZKConfig.JUTE_MAXBUFFER,
                packetLen);
    } catch (NumberFormatException e) {
        String msg = MessageFormat.format(
                "Configured value {0} for property {1} can not be parsed to int",
                clientConfig.getProperty(ZKConfig.JUTE_MAXBUFFER),
                ZKConfig.JUTE_MAXBUFFER);
        LOG.error(msg);
        throw new IOException(msg);
    }
}

public int getInt(String key, int defaultValue) {
    String value = getProperty(key);
    if (value != null) {
        return Integer.parseInt(value.trim());
    }
    return defaultValue;
}

而筆者最後修改的值爲百億,已然超出了int範圍,所以是無效的配置。至此,原因找到了,立馬改成了10M的配置重新啓動zk並刪除/hbase節點成功。

但是,調整此參數始終治標不治本,結合本司集羣中的數據量(200億+)和region數量(10W+)考慮,master重啓是一項浩大的工程,因爲重啓會導致region的狀態變更,而變更的中間狀態是在zk節點維護,當大量的region需要分配,而分配速度又很慢就會導致zk中/hbase/下的部分節點存儲數據量太大從而導致異常。

所以我們需要從兩個方面入手:
1、儘量合理的劃分region。
2、提高處理region分配的線程數。修改配置項hbase.assignment.threads.max,該配置默認值爲30。

<property>
        <name>hbase.assignment.threads.max</name>
        <value>100</value>
</property>

然後重啓HBase,順利啓動。

往期推薦
▬
Uber基於Apache Hudi構建PB級數據湖實踐

數據湖 | 一文讀懂Data Lake的概念、特徵、架構與案例

認識 Delta Lake:讓數倉進化到數據湖

乾貨 | Kafka 內核知識梳理,附思維導圖

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章