Hbase踩坑计

Posted 熙熙

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hbase踩坑计相关的知识,希望对你有一定的参考价值。

Hbase数据库比较适用于写多读少的场景。其查询能力并不突出。
在使用Scan扫描表的时候,很容易踩坑。

踩坑1:在表数据量偏大的情况下(比如上千万数据),执行scan提示60000ms的timeout,并且出现OOM。
分析:

scan对象有几个重要的参数:
  caching:该值表示一次从RPC请求Client可以从Hbase服务器获取的数据条数。
           默认值是-1。按照源码,如果是-1,那么发送给Hbase的值是:HConstants#DEFAULT_HBASE_CLIENT_SCANNER_CACHING,即:
           Integer.MAX_VALUE。 这是一个非常大的值。
           ![image.png](/img/bVcRFNj)

  maxResultSize:client从Hbase服务端获取的数据在客户端缓存的最大字节数。
                 默认是-1。如果使用的是默认值,则缓存大小限制是:2M(即 2 * 1024 * 1024)。   
                 ![image.png](/img/bVcRFNg)
                 
  limit:表示一次Scan扫描的行数,相当于mysql的limit。**需要注意的是:此参数值在2.x版本生效,1.x版本没有此参数。**
         默认值是-1。如果是默认值,则不会使用该参数。

出现这个问题的原因是Hbase-client采用的是2.x版本,但是Hbase服务端是1.x版本。使用limit参数对其无效。所以会一次去
服务端查询Integer.MAX_VALUE条数据,导致OOM和timeout。           

在构造Hbase服务端的请求参数时,代码分别如下(可以看到2.x多了limitOfRows参数):
2.x版本:
public static ScanRequest buildScanRequest(byte[] regionName, Scan scan, int numberOfRows,
      boolean closeScanner) throws IOException {
    ScanRequest.Builder builder = ScanRequest.newBuilder();
    RegionSpecifier region = buildRegionSpecifier(RegionSpecifierType.REGION_NAME, regionName);
    builder.setNumberOfRows(numberOfRows);
    builder.setCloseScanner(closeScanner);
    builder.setRegion(region);
    builder.setScan(ProtobufUtil.toScan(scan));
    builder.setClientHandlesPartials(true);
    builder.setClientHandlesHeartbeats(true);
    builder.setTrackScanMetrics(scan.isScanMetricsEnabled());
    if (scan.getLimit() > 0) {
      builder.setLimitOfRows(scan.getLimit());
    }
    return builder.build();
  }

在1.x版本:

  public static ScanRequest buildScanRequest(final byte[] regionName, final Scan scan,
      final int numberOfRows, final boolean closeScanner) throws IOException {
    ScanRequest.Builder builder = ScanRequest.newBuilder();
    RegionSpecifier region = buildRegionSpecifier(
      RegionSpecifierType.REGION_NAME, regionName);
    builder.setNumberOfRows(numberOfRows);
    builder.setCloseScanner(closeScanner);
    builder.setRegion(region);
    builder.setScan(ProtobufUtil.toScan(scan));
    builder.setClientHandlesPartials(true);
    builder.setClientHandlesHeartbeats(true);
    builder.setTrackScanMetrics(scan.isScanMetricsEnabled());
    return builder.build();
  }

踩坑2:在进行Scan扫描的时候,随着时间的推移,Scan的速度越来越慢。
分析:Scan有2个参数:

  startRow:扫描的起始rowkey。
  filter:值过滤器,比如:RowFilter。 其处理代码如下:
byte[] startRow = scan.getStartRow();
   if (startRow != null && startRow.length > 0) {
     scanBuilder.setStartRow(ByteStringer.wrap(startRow));
   }
   byte[] stopRow = scan.getStopRow();
   if (stopRow != null && stopRow.length > 0) {
     scanBuilder.setStopRow(ByteStringer.wrap(stopRow));
   }
   if (scan.hasFilter()) {
     scanBuilder.setFilter(ProtobufUtil.toFilter(scan.getFilter()));
   }

在使用scan进行全表扫描的时候,如果没有指定startRow,那么就会越来越慢。因为每次都是从头开始扫描,所以会越来越慢。
所以startRow尽量都要添加上。

以上是关于Hbase踩坑计的主要内容,如果未能解决你的问题,请参考以下文章

引入typescript踩坑计(完)

HBase眼高手低从Shell到IDEA编程心路笔记踩坑过程

[转]Spark 踩坑记:数据库(Hbase+Mysql)

spark踩坑——dataframe写入hbase连接异常

Spark踩坑记——数据库(Hbase+Mysql)转

zabbix监控centos服务器部署(去坑计)