HBase运维 | HBase宕机恢复案例一则

2020-06-18 16:52:00 浏览数 (1)

下图为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源码看看到底怎么回事。

代码语言:javascript复制
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(默认值),所以抛出上述异常:

代码语言:javascript复制
private int packetLen = ZKClientConfig.CLIENT_MAX_PACKET_LENGTH_DEFAULT;

查看源码发现zk初始化的时候会去加载配置文件的·jute.maxbuffer·值,如果值的大小不为空就采用此值,如果为空就用默认值,上图红色部分为默认是大小4M=4194304,但还有一个前提就是配置的值必须是int范围内的值,否则Integer.parseInt(value.trim())方法会报错。

代码语言:javascript复制
    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。

代码语言:javascript复制
<property>
        <name>hbase.assignment.threads.max</name>
        <value>100</value>
</property>

然后重启HBase,顺利启动。

微信扫一扫,关注我微信扫一扫,关注我

0 人点赞