2012-04-13 2 views
2

Я пытаюсь выполнить простые работы по сокращению карты для данных, хранящихся в Cassandra, с использованием Java-Client 'HECTOR'.Запуск mapreduce по данным Cassandra с использованием Hector

Я уже успел использовать пример примера из-за -договора, объясненный в этом прекрасном blogpost. Я также прочитал статью Hadoop Support.

Но то, что я хочу сделать, немного отличается с точки зрения реализации (пример wordcount использует скрипт, где упоминается mapreduce-site.xml). Я хотел бы, чтобы кто-то помог мне понять, как я могу выполнять задания по уменьшению числа карт в распределенном режиме, а не локально, из «HECTOR» на данные кассандры.

Мой код запускает работу по сокращению карты УСПЕШНО в локальном режиме. Но я хочу запустить их в распределенном режиме и записать результат как новый ColumnFamily в пространстве ключей cassandra.

я мог бы установить это где-то (как указано в BlogPost упомянутой выше)
$PATH_TO_HADOOP/conf/mapred-site.xml
для запуска его в распределенном режиме, но я не знаю, где.

Вот мой код

public class test_forum implements Tool { 

private String KEYSPACE = "test_forum"; 
private String COLUMN_FAMILY ="posts"; 
private String OUTPUT_COLUMN_FAMILY = "output_post_count"; 
private static String CONF_COLUMN_NAME = "text"; 


public int run(String[] strings) throws Exception { 

    Configuration conf = new Configuration(); 

    conf.set(CONF_COLUMN_NAME, "text"); 
    Job job = new Job(conf,"test_forum"); 

    job.setJarByClass(test_forum.class); 
    job.setMapperClass(TokenizerMapper.class); 
    job.setReducerClass(ReducerToCassandra.class); 

    job.setMapOutputKeyClass(Text.class); 
    job.setMapOutputValueClass(IntWritable.class); 

    job.setOutputKeyClass(ByteBuffer.class); 
    job.setOutputValueClass(List.class); 

    job.setOutputFormatClass(ColumnFamilyOutputFormat.class); 
    job.setInputFormatClass(ColumnFamilyInputFormat.class); 


    System.out.println("Job Set"); 


    ConfigHelper.setRpcPort(job.getConfiguration(), "9160"); 
    ConfigHelper.setInitialAddress(job.getConfiguration(), "localhost"); 
    ConfigHelper.setPartitioner(job.getConfiguration(), "org.apache.cassandra.dht.RandomPartitioner"); 

    ConfigHelper.setInputColumnFamily(job.getConfiguration(),KEYSPACE,COLUMN_FAMILY); 
    ConfigHelper.setOutputColumnFamily(job.getConfiguration(), KEYSPACE, OUTPUT_COLUMN_FAMILY); 

    SlicePredicate predicate = new SlicePredicate().setColumn_names(Arrays.asList(ByteBufferUtil.bytes("text"))); 

    ConfigHelper.setInputSlicePredicate(job.getConfiguration(),predicate); 

    System.out.println("running job now.."); 

    boolean success = job.waitForCompletion(true); 

    return success ? 0:1; //To change body of implemented methods use File | Settings | File Templates. 

} 



public static class TokenizerMapper extends Mapper<ByteBuffer, SortedMap<ByteBuffer, IColumn>, Text, IntWritable> 
{ 
    private final static IntWritable one = new IntWritable(1); 
    private Text word = new Text(); 
    private ByteBuffer sourceColumn; 
    protected void setup(org.apache.hadoop.mapreduce.Mapper.Context context) 
    throws IOException, InterruptedException 
    { 
     sourceColumn = ByteBufferUtil.bytes(context.getConfiguration().get(CONF_COLUMN_NAME)); 
    } 

    public void map(ByteBuffer key, SortedMap<ByteBuffer, IColumn> columns, Context context) throws IOException, InterruptedException 
    { 



     IColumn column = columns.get(sourceColumn); 

     if (column == null) { 
      return; 
     } 

     String value = ByteBufferUtil.string(column.value()); 
     System.out.println("read " + key + ":" + value + " from " + context.getInputSplit()); 

     StringTokenizer itr = new StringTokenizer(value); 

     while (itr.hasMoreTokens()) 
     { 
      word.set(itr.nextToken()); 
      context.write(word, one); 
     } 
    } 


} 

    public static class ReducerToCassandra extends Reducer<Text, IntWritable, ByteBuffer, List<Mutation>> 
{ 
    private ByteBuffer outputKey; 

    public void reduce(Text word, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException 
    { 
     int sum = 0; 

     byte[] keyBytes = word.getBytes(); 
     outputKey = ByteBuffer.wrap(Arrays.copyOf(keyBytes, keyBytes.length)); 


     for (IntWritable val : values) 
      sum += val.get(); 

     System.out.println(word.toString()+" -> "+sum); 
     context.write(outputKey, Collections.singletonList(getMutation(word, sum))); 

    } 

    private static Mutation getMutation(Text word, int sum) 
    { 
     Column c = new Column(); 
     c.setName(Arrays.copyOf(word.getBytes(), word.getLength())); 
     c.setValue(ByteBufferUtil.bytes(String.valueOf(sum))); 
     c.setTimestamp(System.currentTimeMillis()); 

     Mutation m = new Mutation(); 
     m.setColumn_or_supercolumn(new ColumnOrSuperColumn()); 
     m.column_or_supercolumn.setColumn(c); 
     System.out.println("Mutating"); 
     return m; 

    } 

} 




public static void main(String[] args) throws Exception, ClassNotFoundException, InterruptedException { 

    System.out.println("Working..!"); 

    int ret=ToolRunner.run(new Configuration(), new test_forum(), args); 

    System.out.println("Done..!"); 

    System.exit(ret); 

} 

}

Вот предупреждения я получаю:

WARN - JobClient     - Use GenericOptionsParser for parsing the arguments. Applications should implement Tool for the same. 
WARN - JobClient     - No job jar file set. User classes may not be found. See JobConf(Class) or JobConf#setJar(String). 

Но код работает успешно выполняет Map-Reduce задачи, но я не знаю, где он записывает данные.

EDIT: Я не создал columnFamily в cassandra для вывода. Поэтому он не писал. Итак, теперь остается единственная проблема: как запустить ее в распределенном режиме.

спасибо.

ответ

2

Вы создали банку с классом?

Hadoop нуждается в банке, чтобы иметь возможность распространять ваш класс работы над кластером. Если вы этого не сделали, он объяснит ошибку «Нет заданий в файле jar file» и почему вы не можете запустить ее в распределенном режиме. Позаботьтесь о том, чтобы запустить свою работу с помощью команды «hadoop jar ...» и добавить вам зависимости jar (по крайней мере apache-cassandra!). Когда вы отправляете свою работу, ваш сервер cassandra должен быть включен и прослушивать бережливый порт.

Кстати, Hadoop и Cassandra не нуждаются в Гекторе. ColumnFamilyInputFormatColumnFamilyOutputFormat) описывает, как читать (и записывать) данные в Кассандру самостоятельно. Вот почему вам нужно настроить RpcPort, InitialAdress и Partionner (и вы это сделали).

Последнее примечание: ColumnFamilyOutputFormat не будет создавать семейство выходных столбцов, оно должно уже существовать, иначе вы получите сообщение об ошибке при записи.

Надеется, что это помогает,

Benoit