使用map reduce在cassandra中执行批量加载

时间:2013-02-05 05:06:30

标签: hadoop mapreduce cassandra bulk-load datastax-enterprise

我没有太多使用cassandra的经验,所以如果我采取了错误的方法,请原谅我。

我正在尝试使用map reduce

在cassandra中进行批量加载

基本上是单词计数示例

参考:http://henning.kropponline.de/2012/11/15/using-cassandra-hadoopbulkoutputformat/

我已经使用了简单的Hadoop Wordcount Mapper示例,并根据上面的示例略微修改了驱动程序代码和reducer。

我也成功生成了输出文件。现在我的疑问是如何执行加载到cassandra部分?我的方法有什么不同吗?

请建议。

这是驱动程序代码的一部分

 Job job = new Job();
 job.setJobName(getClass().getName());
 job.setJarByClass(CassaWordCountJob.class);

 Configuration conf = job.getConfiguration();
 conf.set("cassandra.output.keyspace", "test");
 conf.set("cassandra.output.columnfamily", "words");
 conf.set("cassandra.output.partitioner.class", "org.apache.cassandra.dht.RandomPartitioner");
 conf.set("cassandra.output.thrift.port","9160");    // default
 conf.set("cassandra.output.thrift.address", "localhost");
 conf.set("mapreduce.output.bulkoutputformat.streamthrottlembits", "400");

 job.setMapperClass(CassaWordCountMapper.class);
 job.setMapOutputKeyClass(Text.class);
 job.setMapOutputValueClass(IntWritable.class);
 FileInputFormat.setInputPaths(job, new Path(args[0]));
 job.setReducerClass(CassaWordCountReducer.class);
 FileOutputFormat.setOutputPath(job, new Path("/home/user/Desktop/test/cassandra")); 
 MultipleOutputs.addNamedOutput(job, "reducer", BulkOutputFormat.class, ByteBuffer.class, List.class);
 return job.waitForCompletion(true) ? 0 : 1;

Mapper与正常的wordcount映射器相同,只是标记并发出Word,1

reducer类的格式为

public class CassaWordCountReducer extends 
        Reducer<Text, IntWritable, ByteBuffer, List<Mutation>> {

    @Override
    public void reduce(Text key, Iterable<IntWritable> values, Context context)
            throws IOException, InterruptedException {
        List<Mutation> columnsToAdd = new ArrayList<Mutation>();
        Integer wordCount = 0;
        for(IntWritable value : values) {
            wordCount += value.get();
        }
        Column countCol = new Column(ByteBuffer.wrap("count".getBytes()));
        countCol.setValue(ByteBuffer.wrap(wordCount.toString().getBytes()));
        countCol.setTimestamp(new Date().getTime());
        ColumnOrSuperColumn wordCosc = new ColumnOrSuperColumn();
        wordCosc.setColumn(countCol);
        Mutation countMut = new Mutation();
        countMut.column_or_supercolumn = wordCosc;
        columnsToAdd.add(countMut);
        context.write(ByteBuffer.wrap(key.toString().getBytes()), columnsToAdd);
    }
}

1 个答案:

答案 0 :(得分:3)

要向Cassandra进行批量加载,我建议查看this article from DataStax。基本上你需要为批量加载做两件事:

  • 您的输出数据本身不适合Cassandra,您需要将其转换为SSTable。
  • 获得SSTable后,您需要能够将它们传输到Cassandra。当然,您不只是想将每个SSTable复制到每个节点,您只想将相关的数据部分复制到每个节点

在您使用BulkOutputFormat的情况下,它应该完成所有操作,因为它使用幕后的sstableloader。我从未在MultipleOutputs中使用它,但它应该可以正常工作。

我认为您的错误是因为您没有正确使用MultipleOutputs:当您真正写入context.write对象时,您仍在执行MultipleOutputs 。你现在正在这样做的方式,因为你写的是常规Context,它将被TextOutputFormat的默认输出格式所取代,而不是你在{MultipleOutputs中定义的格式。 1}}。有关如何在缩减器here中使用MultipleOutputs的更多信息。

一旦您按照您定义的那样写入BulkOutputFormat的正确输出格式,您的SSTable应该从集群中的每个节点创建并流式传输到Cassandra - 您不需要任何额外的步骤,输出格式将为你照顾它。

另外,我建议您查看this post,他们还会解释如何使用BulkOutputFormat,但他们使用的是ConfigHelper,您可能需要查看更多内容轻松配置您的Cassandra端点。