You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java应用中创建HBase Region时触发DoNotRetryRegionException错误的求助:仅成功创建1个Region,其余失败

解决HBase Java客户端异步Split Region时的DoNotRetryRegionException问题

首先咱们来拆解下你遇到的核心问题:

Caused by: org.apache.hadoop.hbase.ipc.RemoteWithExtrasException(org.apache.hadoop.hbase.client.DoNotRetryRegionException): org.apache.hadoop.hbase.client.DoNotRetryRegionException: bc3ec95b447809887e3c198afe4d1084 is not OPEN; regionState={bc3ec95b447809887e3c198afe4d1084 state=CLOSING, ts=1651224527248, server=hbase-docker,16020,1651207907804}

这个报错的本质是:你在循环里反复对同一个正在关闭的Region执行Split操作。HBase执行Region Split时,原Region会先进入CLOSING状态,完成Split后会被移除,同时生成两个新的子Region。而你的代码用了splitRegionAsync异步方法,调用后立刻就去拿最后一个Region(还是那个正在关闭的原Region)并再次发起Split,这时候原Region已经不是OPEN状态,自然就抛出了这个异常。

再看你的代码逻辑:

byte[][] splits = getSplits(countSplits, countSlot);
for (byte[] byteSplit : splits) {
    byte[] regionName = admin.getRegions(tableName).get(admin.getRegions(tableName).size() - 1).getRegionName();
    admin.splitRegionAsync(regionName, byteSplit);
}

这里存在两个关键问题:

  1. 异步操作未等待完成:splitRegionAsync是异步执行的,不会阻塞当前线程,导致下一次循环立刻触发对同一个Region的操作。
  2. 错误的Region选择逻辑:每次都拿当前表的最后一个Region,但Split完成后原Region会被移除,新的子Region会加入,你的逻辑没有跟踪需要Split的目标Region。

解决方案

针对你的需求,有两种可行的修改方式:

方式一:使用同步Split方法(适合新手,逻辑更直观)

把异步的splitRegionAsync换成同步的splitRegion方法,这样每次Split都会等待操作完成后再进行下一次循环,确保每次操作的Region都是处于OPEN状态的:

byte[][] splits = getSplits(countSplits, countSlot);
for (byte[] byteSplit : splits) {
    // 获取当前表的所有Region,选择最后一个可Split的OPEN状态Region
    List<RegionInfo> regions = admin.getRegions(tableName);
    RegionInfo targetRegion = regions.get(regions.size() - 1);
    // 同步执行Split,等待操作完成
    admin.splitRegion(targetRegion.getRegionName(), byteSplit);
}

方式二:正确处理异步操作的Future(适合需要异步场景)

如果你必须使用异步操作,需要等待每个splitRegionAsync返回的CompletableFuture完成后,再进行下一次Split,同时更新要操作的Region:

byte[][] splits = getSplits(countSplits, countSlot);
for (byte[] byteSplit : splits) {
    List<RegionInfo> regions = admin.getRegions(tableName);
    RegionInfo targetRegion = regions.get(regions.size() - 1);
    // 发起异步Split并等待完成
    admin.splitRegionAsync(targetRegion.getRegionName(), byteSplit)
          .join(); // 等待异步操作完成
}

额外建议

如果你需要批量Split到指定数量的Region,其实可以在创建表的时候直接指定预分区,这样更高效,还能避免后续手动Split带来的集群负载波动:

// 创建表时指定预分区
HTableDescriptor tableDesc = new HTableDescriptor(TableName.valueOf("your_table"));
tableDesc.addFamily(new HColumnDescriptor("cf"));
admin.createTable(tableDesc, splits); // splits就是你的预分区数组

内容的提问来源于stack exchange,提问作者Dark Morning

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 20:07:44