在Hbase中,ResultScanner和initTableMapperJob之间的扫描有何不同

时间:2017-07-10 07:57:10

标签: hadoop hbase

我希望有人能告诉我这两个API调用之间的区别是什么。我在他们两个之间得到了奇怪的结果。这发生在hbase-client / hbase-server版本1.0.1和1.2.0-cdh5.7.2。

首先,我的rowkeys的格式为hash_name_timestamp 例如100_servername_1234567890。 hbase表的TTL为30天,因此30天以后的事情应该在压缩后消失。

以下是使用ResultScanner的代码。它不使用MapReduce,因此需要很长时间才能完成。我不能这样做我的工作,因为它需要太长时间。但是,出于调试目的,我对此方法没有任何问题。它列出了指定时间范围内的所有密钥,这些密钥看起来对我有效,因为返回密钥的所有时间戳都在过去30天内且在指定的时间范围内:

Scan scan = new Scan();
scan.addColumn(Bytes.toBytes("raw_data"), Bytes.toBytes(fileType));
scan.setCaching(500);
scan.setCacheBlocks(false);
scan.setTimeRange(start, end);

Connection fConnection = ConnectionFactory.createConnection(conf);
Table table = fConnection.getTable(TableName.valueOf(tableName));
ResultScanner scanner = table.getScanner(scan);
for (Result result = scanner.next(); result != null; result = scanner.next()) {
   System.out.println("Found row: " + Bytes.toString(result.getRow()));
}

以下代码不起作用,但它使用MapReduce,它比使用ResultScanner方式运行得更快,因为它将事物划分为1200个地图。问题是我得到了因TTL过期而应该消失的rowkeys:

Scan scan = new Scan();
scan.addColumn(Bytes.toBytes("raw_data"), Bytes.toBytes(fileType));
scan.setCaching(500);
scan.setCacheBlocks(false);
scan.setTimeRange(start, end);
TableMapReduceUtil.initTableMapperJob(tableName, scan, MTTRMapper.class, Text.class, IntWritable.class, job);

这是我得到的错误,最终会导致整个MR作业失败,因为超过25%的地图制作者失败了。

  

错误:org.apache.hadoop.hbase.client.RetriesExhaustedException:   尝试= 36后失败,例外:2017年6月28日星期三13:46:57,   null,java.net.SocketTimeoutException:callTimeout = 120000,   callDuration = 120301:row'65_app129041.iad1.mydomain.com_1476641940'   在表'server_based_data'在region = server_based_data

我将尝试研究hbase-client和hbase-server jar的代码,但希望有人会知道方法之间的区别是什么以及导致initTableMapperJob调用失败的原因。

编辑:这是我正在使用的表格的描述:

describe 'server_based_data'
Table server_based_data is ENABLED                                              
server_based_data                                                               
COLUMN FAMILIES DESCRIPTION                                                     
{NAME => 'raw_data', DATA_BLOCK_ENCODING => 'NONE', BLOOMFILTER => 'ROW', REPLIC
ATION_SCOPE => '0', VERSIONS => '1', COMPRESSION => 'SNAPPY', MIN_VERSIONS => '0
', TTL => '2592000 SECONDS (30 DAYS)', KEEP_DELETED_CELLS => 'FALSE', BLOCKSIZE 
=> '65536', IN_MEMORY => 'false', BLOCKCACHE => 'true'}                         
1 row(s) in 0.5180 seconds

这是我的映射器代码:

public void map(ImmutableBytesWritable rowkey, Result columns, Context context) throws IOException, InterruptedException {
    Configuration conf = context.getConfiguration();
    startMS = conf.getLong("startTime", 0);
    endMS = conf.getLong("endTime", 1);
    System.out.println(startMS);
    System.out.println(endMS);

    // extract the ci as the key from the rowkey
    String pattern = "\\d*_(\\S*)_(\\d{10})";
    String ciname = null;
    Pattern r = Pattern.compile(pattern);
    String strRowKey = Bytes.toString(rowkey.get());
    // check the time here to see if we count it or not in the counts

    Matcher m = r.matcher(strRowKey);
    long ts = 0;

    if (m.find()) {
        ts = Long.valueOf(m.group(2)).longValue();
        ciname = m.group(1);
        if ((ts >= startMS) && (ts <= endMS)) {
            context.write(new Text(ciname), ONE);           
        }           
    }       
}

我仍然认为initTableMapperJob方法有一些东西,因为上面发布的错误显示了一个应该从表的TTL过期的行的时间戳但是由于某种原因,initTableMapperJob仍然找到它并尝试寻找它但是超时,而ResultScanner由于某种原因没有看到它。

1 个答案:

答案 0 :(得分:1)

我想提出几点建议。

  1. 查看Spark on HBase examples,特别是如何使用Spark执行扫描。它是用Scala编写的,但您可以在Java中实现相同的功能。即使在这种情况下,它也会比MapReduce代码简洁。
  2. 如果只需要行键,请添加相应的过滤器,例如FirstKeyOnlyFilter。这将减少从HBase检索到的不必要数据量。
  3. 我不确定导致initTableMapperJob奇怪行为的原因。但我希望上述建议有用。