IT技术博客大学习 共学习 共进步

HBase集群出现NotServingRegionException问题的排查及解决方法

量子恒道官方博客 2012-12-21 13:37:58 浏览 17,123 次

HBase集群在读写过程中,可能由于Region Split或Region Blance等导致Region的短暂下线,此时客户端与HBase集群进行RPC操作时会抛出NotServingRegionException异常,从而导致读写操作失败。这里根据实际项目经验,详细描述这一问题的发现及排查解决过程。

1. 发现问题

在对HBase集群进行压力测试过程中发现,当实际写入HBase和从HBase查询的量是平时的若干倍时(集群规模10~20台,每秒读写数据量在几十万条记录的量级),导致集群的读写出现一定程度的波动。具体如下:

1)写端抛出以下异常信息:

org.apache.hadoop.hbase.client.RetriesExhaustedWithDetailsException: Failed 150 actions: NotServingRegionException: 150 times, servers with issues: my161208.cm6:60020,at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.processBatchCallback(HConnectionManager.java:1600)at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.processBatch(HConnectionManager.java:1376)at org.apache.hadoop.hbase.client.HTable.flushCommits(HTable.java:916)

2)读端也抛出类似异常信息:

org.apache.hadoop.hbase.client.RetriesExhaustedException: Failed after attempts=10, exceptions:Mon Oct 29 14:03:09 CST 2012, org.apache.hadoop.hbase.client.ScannerCallable@3740fb20, org.apache.hadoop.hbase.NotServingRegionException: org.apache.hadoop.hbase.NotServingRegionException: xxxxxx,\x0FP\x8D\xC3\xDB1053223266:\x00\x00V6,1351490475989.bd68113129f07163dc25e78fba17ad6c. is closing

以上异常,在压测期间周期性地出现,HBase集群由此出现了短暂的不可服务期。

2. 排查问题

通 过查看HBase Master运行日志,结合客户端抛出异常的时刻,发现当时HBase集群内正在进行Region的Split和不同机器之间的Region Balance,那么,为什么会周期性频繁触发以上过程呢?而且是发生在压测期间(数据量与平时相比大几倍)。下面结合表的设计来分析一下:

1) 由于表中rowkey有时间字段,因此每天都需要新创建Region,同时由于写入数据量大,进一步触发了HBase的Region Split操作,这一过程一般耗时较长(测试时从线上日志来看,平均为10秒左右,Region大小为4GB),且Region Split操作触发较为频繁;

2)同时由于Region Split操作导致Region分布不均匀,进而触发HBase自动做Region Balance操作,Region迁移过程中也会导致Region下线,这一过程耗时较长(测试时从线上日志来看,平均为20秒左右)。

3. 解决问题

首先,从客户端考虑,其实就是要保证Region下线不可服务期间,读写请求能够在集群恢复后继续,具体可以采取如下措施:

1) 对于写端,可以将未写入成功的记录,添加到一个客户端缓存中,隔一段时间后交给一个后台线程统一重新提交一次;也可以通过 setAutoFlush(flase, false)保证提交失败的记录不被抛弃,留在客户端writeBuffer中等待下次writeBuffer满了后再次尝试提交,直到提交成功为止。

2)对于读端,捕获异常后,可以采取休眠一段时间后进行重试等方式。

3)当然,还可以根据实际情况合理调整hbase.client.retries.number和hbase.client.pause配置选项。

然后,从服务端考虑,需要分别针对Region Split和Region Balance进行解决:

1) 由于建表时,我们已经考虑到了数据在不同Region Server上的均匀分布,而且预先在不同Region Server上创建并分配了相同数目的Region,那么考虑到为了集群能够在实际线上环境下提供稳定的服务,可以选择关掉HBase的Region自动 Balance功能,当然关掉后可以选择在每天读写压力小的时候(如凌晨后)触发执行一次Balance操作即可。

2)接下来,Region总是被创建,不能被复用的问题该如何解决呢?根本原因是rowkey中包含了timestamp字段,而每时每刻timestamp总是 向上增长的。但是,使用方确实需要能够根据timestamp字段进行顺序scan操作,因此,timestamp字段必须保留。据此,这里给出两种解决 思路:

  • 一种常用方法是将表按照时间分表,例如按天进行分表,这样可以通过预先建表创建好Region分区,避免实际读写过程中频 繁触发Region Split等过程,但是这一方法的缺点是每天需要预先建好表,而这一DDL过程可能出现问题进而导致读写出现问题,同时跨天时读写端也需要做出适应,调整 为读写新创建的表。

  • 其实,我们可以换一种思路,通过修改表的rowkey结构,将timestamp字段改成一个周期循环的 timestamp,如取timestamp % TS_MODE后的值,其中TS_MODE须大于等于表的TTL时间周期,这样才能保证数据不会被覆盖掉。经过这样改造后,即可实现Region的复用, 避免Region的无限上涨。对于读写端的变更也较小,读写端操作时只需将timestamp字段取模后作为rowkey进行读写,另外,读端需要考虑能 适应scan扫描时处理[startTsMode, endTsMode]和[endTsMode, startTsMode]两种情况。

4. 总结的话

以上仅是本人结合实际项目中遇到的问题进行了概括总结,仅供参考。欢迎讨论交流。

建议继续学习

  1. HFile存储格式 (阅读 15,822)
  2. hbase运维 (阅读 14,783)
  3. hbase介绍 (阅读 12,225)
  4. HBase技术介绍 (阅读 7,943)
  5. HBase随机写以及随机读性能测试 (阅读 7,422)
  6. HBase性能优化方法总结 (阅读 6,944)
  7. HBase二级索引与Join (阅读 6,861)
  8. HBase Thrift 接口使用注意事项 (阅读 6,602)
  9. Cassandra和HBase主要设计思路对比 (阅读 4,945)
  10. 菜鸟谈HBase之写速度篇 (阅读 4,340)