HBase использует Put из Hadoop, но не видит значения в оболочке HBase - PullRequest
0 голосов
/ 28 февраля 2012

У меня есть простое задание карты / уменьшения, которое сканирует одну таблицу hbase и изменяет другую таблицу hbase.Задание hadoop, кажется, успешно завершено, но когда я проверяю таблицу hbase, запись там не появляется.

Вот программа hadoop:

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.mapreduce.TableMapReduceUtil;
import org.apache.hadoop.hbase.mapreduce.TableMapper;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.output.NullOutputFormat;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;

public class HBaseInsertTest extends Configured implements Tool {

    @Override
    public int run(String[] args) throws Exception {
        String table = "duplicates";

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

        Job job = new Job(getConf(), "HBaseInsertTest");
        job.setJarByClass(HBaseInsertTest.class);

        TableMapReduceUtil.initTableMapperJob(table, scan, Mapper.class, /* mapper output key = */null,
            /* mapper output value= */null, job);
        TableMapReduceUtil.initTableReducerJob("tablecopy", /*output table=*/null, /*reducer class=*/job);

        job.setNumReduceTasks(0);

        // Note that these are the default.
        job.setOutputFormatClass(NullOutputFormat.class);

        return job.waitForCompletion(true) ? 0 : 1;
    }

    private static class Mapper extends TableMapper<ImmutableBytesWritable, Put> {
        @Override
        protected void setup(Context context) throws IOException, InterruptedException {
            super.setup(context);
        }

        @Override
        public void map(ImmutableBytesWritable row, Result columns, Context context) throws IOException {
            long id = 1260018L;

            try {
                Put put = new Put(Bytes.toBytes(id));
                put.add(Bytes.toBytes("mapping"), Bytes.toBytes("foo"), Bytes.toBytes("bar"));
                context.write(row, put);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws Exception {
        Configuration config = HBaseConfiguration.create();
        int res = ToolRunner.run(config, new HBaseInsertTest(), args);
        System.exit(res);
    }
}

Из оболочки HBase:

hbase(main):008:0> get 'tablecopy', '1260018', 'mapping'
COLUMN                          CELL                                                                                    
0 row(s) in 0.0100 seconds

Я значительно упростил программу, чтобы попытаться продемонстрировать / изолировать проблему,Я также относительно новичок в обоих hadoop / hbase.Я проверил, что отображение - это семейство столбцов, которое существует в таблице tablecopy.

Ответы [ 2 ]

2 голосов
/ 23 марта 2012

Я думаю, проблема в том, что вы запрашивали hbase (main): 008: 0> get 'tablecopy', '1260018', 'mapping'

вместо этого вы должны были бы запросить это: hbase (main): 008: 0> get 'tablecopy', 1260018, 'mapping'

HBase думал, что это строковый ключ, к которому вы обращались из-за цитат. Кроме того, если вы просто запустите на своем конце простое клиентское задание для извлечения этого ключа из HBase, он получит правильные значения, если он уже присутствует.

0 голосов
/ 02 марта 2012

Ваша проблема заключается в отсутствии у вас редуктора. Вам нужно создать класс, расширяющий TableReducer, который принимает в качестве входных данных Put и использует context.write(ImmutableBytesWritable key, Put put) для записи этого Put в целевую таблицу.

Я представляю, что это выглядит примерно так:

public static class MyReducer extends TableReducer<ImmutableBytesWritable, Put, ImmutableBytesWritable> {

  public void reduce(ImmutableBytesWritable key, Iterable<Put> values, Context context)
      throws IOException, InterruptedException {
    for (Put record : values) {
      context.write(key, record);
    }
  }
}

Затем вы изменяете свой инициализатор редуктора стола так: TableMapReduceUtil.initTableReducerJob("tablecopy", MyReducer.class, job);

Это должно сделать это. Другой вариант заключается в том, чтобы по-прежнему не иметь редуктора, открыть объект HTable в маппере и написать пропущенный через него текст прямо так:

HTable table = new HTable(Context.getConfiguration(), "output_table_name");
Put myPut = ...;
table.put(myPut);
table.close();

Надеюсь, это поможет!

...