【问题标题】:HBase bulk delete using MapReduce job使用 MapReduce 作业的 HBase 批量删除
【发布时间】:2014-06-09 00:20:16
【问题描述】:

我正在尝试使用 mapreduce 作业从 Hbase 表中删除行。

我收到以下错误。

java.lang.ClassCastException: org.apache.hadoop.hbase.client.Delete cannot be cast to org.apache.hadoop.hbase.KeyValue
        at org.apache.hadoop.hbase.mapreduce.HFileOutputFormat$1.write(HFileOutputFormat.java:124)
        at org.apache.hadoop.mapred.ReduceTask$NewTrackingRecordWriter.write(ReduceTask.java:551)
        at org.apache.hadoop.mapreduce.task.TaskInputOutputContextImpl.write(TaskInputOutputContextImpl.java:85)
        at org.apache.hadoop.mapreduce.lib.reduce.WrappedReducer$Context.write(WrappedReducer.java:99)
        at org.apache.hadoop.mapreduce.Reducer.reduce(Reducer.java:144)
        at org.apache.hadoop.mapreduce.Reducer.run(Reducer.java:164)
        at org.apache.hadoop.mapred.ReduceTask.runNewReducer(ReduceTask.java:610)
        at org.apache.hadoop.mapred.ReduceTask.run(ReduceTask.java:444)
        at org.apache.hadoop.mapred.Child$4.run(Child.java:268)
        at java.security.AccessController.doPrivileged(Native Method)
        at javax.security.auth.Subject.doAs(Subject.java:396)
        at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.

看起来这是由 configureIncrementalLoad 设置为 KeyValue 的输出引起的。它只有 PutSortReducer 和 KeyValueSortReducer,但没有 DeleteSortReducer。

我的代码:

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.client.Delete;
import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.mapreduce.HFileOutputFormat;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.GenericOptionsParser;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;

public class DeleteRows extends Configured implements Tool {

    public static class Map extends
            Mapper<LongWritable, Text, ImmutableBytesWritable, Delete> {

        ImmutableBytesWritable hKey = new ImmutableBytesWritable();
        Delete delRow;

        @Override
        protected void map(LongWritable key, Text value, Context context)
                throws IOException, InterruptedException {
            hKey.set(value.getBytes());
            delRow = new Delete(hKey.get());
            context.write(hKey, delRow);
            // Update counters
            context.getCounter("RowsDeleted", "Success").increment(1);
        }
    }


    @SuppressWarnings("deprecation")
    public int run(String[] args) throws Exception {
        Configuration conf = new Configuration();
        args = new GenericOptionsParser(conf, args).getRemainingArgs();
        HBaseConfiguration.addHbaseResources(conf);

        Job job = new Job(conf, "Delete stuff!");
        job.setJarByClass(DeleteRows.class);

        job.setMapperClass(Map.class);
        job.setMapOutputKeyClass(ImmutableBytesWritable.class);
        job.setMapOutputValueClass(Delete.class);

        job.setInputFormatClass(TextInputFormat.class);
        FileInputFormat.addInputPath(job, new Path(args[0]));

        HTable hTable = new HTable(args[2]);
        // Auto configure partitioner and reducer
        HFileOutputFormat.configureIncrementalLoad(job, hTable);
        FileOutputFormat.setOutputPath(job, new Path(args[1]));

        job.waitForCompletion(true);
        return (0);
    }

    public static void main(String[] args) throws Exception {
        int exitCode = ToolRunner.run(new DeleteRows(), args);
        System.exit(exitCode);
    }
}

是否有更好/更快的方法来使用行键删除大量行?显然删除映射器中的每一行是可能的,但是我想这比将删除批量推送到正确的区域服务器要慢。

【问题讨论】:

    标签: java hadoop mapreduce hbase scalability


    【解决方案1】:

    结果是使用TableMapReduceUtil.initTableReducerJob 设置reducer 而不是HFileOutputFormat.configureIncrementalLoad 代码可以正常工作。

    TableMapReduceUtil.initTableReducerJob(tableName, null, job);
    job.setNumReduceTasks(0);
    

    但是,这仍然不会为 completebulkload 实用程序创建删除。它只是执行删除 RPC。

    【讨论】:

      【解决方案2】:

      您的目标是在内部生成带有Delete 流(实际上删除标记为KeyValue)的HFile。这样做的标准方法是使用HFileOutputFormat。实际上,您只能将KeyValue 的流更改为这种格式,并且有 2 个标准减速器:PutSortReducerKeyValueSortReducer。将减少任务的数量设置为 0,您实际上将所有 Delete 直接传递给输出格式,这当然不能工作。

      您最明显的选择:

      • 添加您的减速器DeleteSortReducer。这样的减速器非常简单,你几乎可以复制。您只需要从 Delete 中提取单个 KeyValue 流并对其进行排序。 PutSortReducer 是你的好榜样。 Put 更改没有排序,所以这就是需要这样的 reducer 的原因。
      • 只是构造不是Delete 的流,而是包含删除标记的适当KeyValue 的流。这可能是提高速度的最佳选择。

      【讨论】:

      • Roman,创建一个包含删除标记的适当KeyValue 是什么意思?维护我自己的字段,确定该行是否被删除,然后定期清理所有需要删除的行?
      • 不,HBase 中的删除实际上是标记而不是操作:hadoop-hbase.blogspot.com/2011/12/deletion-in-hbase.html
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多