对 HBase 进行 scan 的时候,有时会出现 ScannerTimeoutException 异常,异常如下:
Error: org.apache.hadoop.hbase.client.ScannerTimeoutException: 4196754ms passed since the last invocation, timeout is currently set to 60000
at org.apache.hadoop.hbase.client.ClientScanner.loadCache(ClientScanner.java:434)
at org.apache.hadoop.hbase.client.ClientScanner.next(ClientScanner.java:364)
at org.apache.hadoop.hbase.mapreduce.TableRecordReaderImpl.nextKeyValue(TableRecordReaderImpl.java:222)
at org.apache.hadoop.hbase.mapreduce.TableRecordReader.nextKeyValue(TableRecordReader.java:147)
at org.apache.hadoop.hbase.mapreduce.TableInputFormatBase$1.nextKeyValue(TableInputFormatBase.java:216)
at org.apache.hadoop.mapred.MapTask$NewTrackingRecordReader.nextKeyValue(MapTask.java:556)
at org.apache.hadoop.mapreduce.task.MapContextImpl.nextKeyValue(MapContextImpl.java:80)
at org.apache.hadoop.mapreduce.lib.map.WrappedMapper$Context.nextKeyValue(WrappedMapper.java:91)
at org.apache.hadoop.mapreduce.Mapper.run(Mapper.java:144)
at org.apache.hadoop.mapred.MapTask.runNewMapper(MapTask.java:787)
at org.apache.hadoop.mapred.MapTask.run(MapTask.java:341)
at org.apache.hadoop.mapred.YarnChild$2.run(YarnChild.java:164)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:415)
at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1693)
at org.apache.hadoop.mapred.YarnChild.main(YarnChild.java:158)
如果在 scan hbase 的时候见到如上报错,可能的原因是,你某两次 scan 的触发的间隔时间过长。分析如下原因:
1. 是否你自己每次的 scan 处理较耗时? -> 优化处理程序,scan 一些设置调优(比如 setBlockCache(false) )
2. 是否每次 scan 的 caching 设置过大? -> 减少 caching (一般默认先设 100)
3. 是否是网络或机器负载问题? -> 联系运维跟进查看集群原因
4. 是否 HBase 本身负载问题? -> 查看 RegionServer 日志
hbase1.1.2 源码是
this.scannerTimeout = HBaseConfiguration.getInt(conf,
HConstants.HBASE_CLIENT_SCANNER_TIMEOUT_PERIOD,
HConstants.HBASE_REGIONSERVER_LEASE_PERIOD_KEY,
HConstants.DEFAULT_HBASE_CLIENT_SCANNER_TIMEOUT_PERIOD);
查看HConstants.HBASE_REGIONSERVER_LEASE_PERIOD_KEY和HConstants.DEFAULT_HBASE_REGIONSERVER_LEASE_PERIOD
我们可以得知如果没有设置 HConstants.HBASE_REGIONSERVER_LEASE_PERIOD_KEY 那么他们采用默认值即
public static long DEFAULT_HBASE_REGIONSERVER_LEASE_PERIOD = 60000;
跟踪:ClientScanner.lastNext 发现此为上次访问时间
解决方案:
可以通过设置 HConstants.HBASE_REGIONSERVER_LEASE_PERIOD_KEY解决
代码如下:
config.setLong(HConstants.HBASE_REGIONSERVER_LEASE_PERIOD_KEY, 120000);
如果不想在代码中修改配置文件,可以直接修改集群中的配置,在 hbase 中找到对应的配置,然后进行修改