将Spark RDD中的值放入具有默认时间戳的同一HBase列

时间:2016-07-07 08:51:12

标签: java hadoop apache-spark hbase

我正在使用Spark并尝试将RDD写入HBase表。

示例代码:

public static void main(String[] args) {
// ... code omitted
    JavaPairRDD<ImmutableBytesWritable, Put> hBasePutsRDD = rdd
            .javaRDD()
            .flatMapToPair(new MyFunction());

    hBasePutsRDD.saveAsNewAPIHadoopDataset(job.getConfiguration());
}

private class MyFunction implements
            PairFlatMapFunction<Row, ImmutableBytesWritable, Put> {

    public Iterable<Tuple2<ImmutableBytesWritable, Put>> call(final Row row) 
            throws Exception {

        List<Tuple2<ImmutableBytesWritable, Put>> puts = new ArrayList<>();
        Put put = new Put(getRowKey(row));
        String value = row.getAs("rddFieldName");

        put.addColumn("CF".getBytes(Charset.forName("UTF-8")), 
                      "COLUMN".getBytes(Charset.forName("UTF-8")),
                      value.getBytes(Charset.forName("UTF-8")));

        return Collections.singletonList(
            new Tuple2<>(new ImmutableBytesWritable(getRowKey(row)), put));
    }
}

如果我手动设置这样的时间戳:

put.addColumn("CF".getBytes(Charset.forName("UTF-8")), 
              "COLUMN".getBytes(Charset.forName("UTF-8")),
              manualTimestamp,
              value.getBytes(Charset.forName("UTF-8")));

一切正常,我在HBase列“COLUMN”中有尽可能多的单元版本,因为RDD中有许多不同的值。

但如果我不这样做,那么只有一个单元版本。

换句话说,如果有多个Put对象具有相同列族和列,不同值和默认时间戳,则只有将插入一个值,另一个将被省略(可能被覆盖)。

在这种情况下,请你帮我理解它的工作原理(特别是 saveAsNewAPIHadoopDataset )以及如何修改代码以插入值而不是手动设置时间戳。

1 个答案:

答案 0 :(得分:3)

当您不使用时间戳时,它们会被覆盖。 Hbase需要每个值的唯一键,因此每个值的真正关键是

rowkey + column family + column key + timestamp => value

当您不使用时间戳,并且它们作为批量插入时,其中许多都获得相同的时间戳,因为hbase可以在相同的毫秒内插入多行。因此,您需要为每个相同的列键值设置自定义时间戳。

我不明白为什么你不想使用自定义时间戳,因为你已经说它已经有效了。如果您认为它将在数据库中使用额外的空间,即使您没有使用Put命令,hbase也已经使用了时间戳。因此,当您使用手动时间戳时,没有任何变化,请使用它。