java - Hbase mapreduce 作业 : all column values are null

标签 java hadoop mapreduce hbase

我正在尝试在 HBase 数据库的表上用 Java 创建一个 map-reduce 作业。使用 here 中的示例和互联网上的其他东西,我设法成功地编写了一个简单的行计数器。但是,尝试编写一个实际对列中的数据执行某些操作的程序是不成功的,因为接收到的字节始终为空。

我的 Driver 工作的一部分是这样的:

/* Set main, map and reduce classes */
job.setJarByClass(Driver.class);
job.setMapperClass(Map.class);
job.setReducerClass(Reduce.class);

Scan scan = new Scan();
scan.setCaching(500);
scan.setCacheBlocks(false);

/* Get data only from the last 24h */
Timestamp timestamp = new Timestamp(System.currentTimeMillis());
try {
    long now = timestamp.getTime();
    scan.setTimeRange(now - 24 * 60 * 60 * 1000, now);
} catch (IOException e) {
    e.printStackTrace();
}

/* Initialize the initTableMapperJob */
TableMapReduceUtil.initTableMapperJob(
        "dnsr",
        scan,
        Map.class,
        Text.class,
        Text.class,
        job);

/* Set output parameters */
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(Text.class);
job.setOutputFormatClass(TextOutputFormat.class);

如您所见,该表名为 dnsr。我的映射器看起来像这样:

@Override
    public void map(ImmutableBytesWritable row, Result value, Context context)
            throws InterruptedException, IOException {
        byte[] columnValue = value.getValue("d".getBytes(), "fqdn".getBytes());
        if (columnValue == null)
            return;

        byte[] firstSeen = value.getValue("d".getBytes(), "fs".getBytes());
        // if (firstSeen == null)
        //     return;

        String fqdn = new String(columnValue).toLowerCase();
        String fs = (firstSeen == null) ? "empty" : new String(firstSeen);

        context.write(new Text(fqdn), new Text(fs));
    }

一些注意事项:

  • dnsr 表中的列族只是d。有多个列,其中一些被称为 fqdnfs (firstSeen);
  • 即使 fqdn 值显示正确,fs 始终是“空”字符串(我在遇到一些错误表明您无法将 null 转换为新字符串后添加了此检查字符串);
  • 如果我用其他名称更改 fs 列名称,例如 ls (lastSeen),它会起作用;
  • reducer 什么都不做,只是输出它接收到的所有内容。

我在 javascript 中创建了一个简单的表扫描器,它正在查询完全相同的表和列,我可以清楚地看到那里的值。使用命令行并手动执行查询,我可以清楚地看到 fs 值不为空,它们是稍后可以转换为字符串(表示日期)的字节。

我总是得到 null 可能是什么问题?

谢谢!

更新: 如果我获得特定列族中的所有列,我不会收到 fs。但是,用 javascript 实现的简单扫描器将 fs 作为 dnsr 表中的一列返回。

@Override
public void map(ImmutableBytesWritable row, Result value, Context context)
        throws InterruptedException, IOException {
    byte[] columnValue = value.getValue(columnFamily, fqdnColumnName);
    if (columnValue == null)
        return;
    String fqdn = new String(columnValue).toLowerCase();

    /* Getting all the columns */
    String[] cns = getColumnsInColumnFamily(value, "d");
    StringBuilder sb = new StringBuilder();
    for (String s : cns) {
        sb.append(s).append(";");
    }

    context.write(new Text(fqdn), new Text(sb.toString()));
}

我使用了来自 here 的答案获取所有列名。

最佳答案

最后,我设法找到了“问题”。 Hbase 是一个面向列的数据存储。在这里,数据按列存储和检索,因此如果只需要一些数据,则只能读取相关数据。每个列族都有一个或多个列限定符(列),每一列都有多个单元格。有趣的是每个单元格都有自己的时间戳。

为什么会出现这个问题?那么,当您进行范围搜索时,只会返回时间戳在该范围内的单元格,因此您最终可能会得到包含“缺失单元格”的行。在我的例子中,我有一个 DNS 记录和其他字段,例如 firstSeenlastSeenlastSeen 是每次看到那个域都会更新的字段,firstSeen 会在第一次出现后保持不变。一旦我将远程 map reduce 作业更改为简单的 map reduce 作业(使用所有时间数据),一切都很好(但作业需要更长的时间才能完成)。

干杯!

关于java - Hbase mapreduce 作业 : all column values are null,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55791715/

相关文章:

hadoop - 如何使用SequenceFileInputFormat将字节数组序列化为本地文件

hadoop - 使用 tera gen 时从 kv.local/172.20.12.168 调用 localhost :8020 failed on connection exception,

hadoop - 是否有一个好的库可以帮助使用 Hadoop Streaming 和 Python 链接 MapReduce 作业?

java - 在最新的 Spring v4 中使用带有可选正文的 @RequestBody

java - 按排序顺序将元素插入数组

java - KeyAffinityService 的 NullPointerException

eclipse - 如何干净地卸载 Eclipse MapReduce 插件?

Java如何复制文件的一部分

linux - hive 脚本(hivequery.hql)文件中的这个符号是什么意思 "use ${word:word}"

java - TotalOrderPartitioner 忽略分区文件位置