遇到和修复的一些HBase的coredump问题

本文详细分析了HBase中导致UI coredump的几个关键问题,包括RPC调用参数引用已释放内存、checkAndMutate操作中数据过早释放以及RPC结束后资源释放不当。此外,还提到了文件损坏引发的compaction问题和特定情况下与toobigrequest并存的coredump问题。针对这些问题,文章给出了相应的社区issue链接和部分修复方案,如调整代码逻辑和数据使用时机。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

HBase coredump问题和修复

  1. UI展示RPC call参数时,引用了被释放的内存。UI造成coredump的原因有两个:
  • RPC monitor的生命周期没有控制在call的生命周期之内;
  • RPC monitor返回给http call克隆对象时,状态变量的克隆与数据变量的克隆不匹配。状态变量类似常量拷贝,而数据变量是浅拷贝。
  • 提交到社区的issue:
    https://issues.apache.org/jira/browse/HBASE-25981
    https://issues.apache.org/jira/browse/HBASE-26087
  • 这个bug的触发与运维脚本频繁抓取JMX的内容有关,特别是抓取RPC的处理状态信息。修复前全部集群特别是访问压力大的集群,会间隔几天因这个问题RS coredump重启。
  1. checkAndMutate在check阶段获取的数据被过早释放。
    问题的原因是checkAndMutate在check阶段会scan一部分数据。这部分数据用来做检查。但是scan出数据后,检查之前,scanner就被close,从而数据所在的堆外内存就被释放和复用。
    在读数据内容做check的时候,会因为读取数据内存地址的数据不符合预期而产生错误的判断或是coredump,而错误的判断会导致用户本应写入的数据写入失败。
    这个问题可以用UT稳定复现。解决方案也比较明确,即数据在使用之后释放。
    提到社区的issue:https://issues.apache.org/jira/browse/HBASE-26036
    这个bug主要影响的业务,他们存储的数据有正排属性,比如价格,库存等,所以几乎所有相关的表都会采用CAS写入的方式。

  2. RPC结束close scanner时,发现资源已被释放。
    问题的原因:
    table block进入bucket cache缓存后,block中记录的next block size如果发生变化,会由新的block替换原先缓存的block。
    而这个过程为了避免原先的block发生内存泄漏,替换前会将原block的内存直接释放,释放时并未考虑原block是否有rpc引用。
    提到社区的issue:https://issues.apache.org/jira/browse/HBASE-26155

  3. 文件损坏引起的coredump问题。
    经过日志分析发现多台RS因coredump重启,线程崩溃在解压包的位置。并且最终定位到崩溃与具体的2个region有关,这2个region只要开始做compaction,就会引起RS崩溃。
    整个集群300多台机器,2个region分别坏了1个文件,然后只要compaction选中损坏文件,就会引起region在的RS coredump重启,然后region移动到其他RS,短时间内又回coredump。也就是2个文件损坏,引起了全部RS的轮番重启!
    于是先更新代码将疑似有问题的region全部隔离,禁用疑似问题region的compact,保证服务的可用性。再经过PR检查,代码检查,文件检查。。。最终定位是与2个文件有关,这2个文件有数据损坏/异常,只要调用lzo native lib解压就必定会引起进程崩溃。
    使用HBase提供的shell工具读对应hfile的stat信息时,就会崩溃,确认了这个问题。

  4. 与too big request同时出现的coredump问题。
    但是coredump时调用栈的位置每次都指在WrongRowIOException message的kv.toString()的位置,
    public Put add(Cell kv) throws IOException{
    byte [] family = CellUtil.cloneFamily(kv);
    List list = getCellList(family);
    //Checking that the row of the kv is the same as the put
    if (!CellUtil.matchingRow(kv, this.row)) {
    throw new WrongRowIOException("The row in " + kv.toString() +
    " doesn’t match the original one " + Bytes.toStringBinary(this.row));
    }
    list.add(kv);
    familyMap.put(family, list);
    return this;
    }
    改为如下代码,coredump就不复现了
    if (!CellUtil.matchingRow(kv, this.row)) {
    String errMsg = "The row in the put kv doesn’t match the original one " +
    Bytes.toStringBinary(this.row);
    LOG.error(errMsg);
    throw new WrongRowIOException(errMsg);
    }
    这个问题目前没找到根因,还在跟进中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值