您的位置:首页 > 其它

对于HBase的MapReduce性能提升方案之BulkLoad

2014-10-16 18:14 239 查看
我们知道,在第一次海量数据批量入库时,我们会选择使用BulkLoad的方式。

简介一下BulkLoad原理方式:(1)通过MapReduce的方式,在Map或者Reduce端将输出格式化为HBase的底层存储文件HFile。(2)调用BulkLoad将第一个Job生成的HFile导入到对应的HBase表中。

ps:请注意(1)HFile方式是所有的加载方案里面是最快的,前提是:数据必须第一个导入,表示空的!如果表中已经有数据,HFile再次导入的时候,HBase的表会触发split分割操作。(2)最终输出结果,无论是Map还是Reduce,输出建议只使用<ImmutableBytesWritable, KeyValue>。

现在我们开始正题:BulkLoad固然是写入HBase最快的方式,但是,如果我们在做业务分析的时候,而数据又已经在HBase的时候,我们采用普通的针对HBase的方式,如下demo所示:

import com.yeepay.bigdata.bulkload.TableCreator;
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.mapreduce.TableReducer;
import org.apache.hadoop.mapreduce.Job;
import org.apache.log4j.Logger;

import java.io.IOException;

public class HBaseMapReduceDemo {

static Logger LOG = Logger.getLogger(HBaseMapReduceDemo.class);

static class Mapper1 extends TableMapper<ImmutableBytesWritable, ImmutableBytesWritable> {

@Override
public void map(ImmutableBytesWritable row, Result values, Context context) throws IOException {

try {
// context.write(key, value);
} catch (Exception e) {
LOG.error(e);
}
}
}

public static class Reducer1 extends TableReducer<ImmutableBytesWritable, ImmutableBytesWritable, ImmutableBytesWritable> {

public void reduce(ImmutableBytesWritable key, Iterable<ImmutableBytesWritable> values, Context context) throws IOException, InterruptedException {
try {

Put put = new Put(key.get());
// put.add();
context.write(key, put);

} catch (Exception e) {
LOG.error(e);
return ;
} // catch
} // reduce function
} // reduce class

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

HBaseConfiguration conf = new HBaseConfiguration();
conf.set("hbase.zookeeper.quorum", "yp-name02,yp-name01,yp-data01");
conf.set("hbase.zookeeper.property.clientPort", "2181");
// conf.set(TableInputFormat.INPUT_TABLE,"access_logs");
Job job = new Job(conf, "HBaseMapReduceDemo");
job.setJarByClass(HBaseMapReduceDemo.class);
// job.setNumReduceTasks(2);
Scan scan = new Scan();
scan.setCaching(2500);
scan.setCacheBlocks(false);

TableMapReduceUtil.initTableMapperJob("srcHBaseTableName", scan, Mapper1.class, ImmutableBytesWritable.class, ImmutableBytesWritable.class, job);
// TableCreator.createTable(20, true, "OP_SUM");
TableMapReduceUtil.initTableReducerJob("destHBasetableName", Reducer1.class, job);
System.exit(job.waitForCompletion(true) ? 0 : 1);
}

}
这个时候在对海量数据的插入过程中,会放生Spliter,写入速度非常的,及其的慢。但是此种情况适合,对已有的HBase表进行修改时候的使用。
针对如下情况HBase -> MapReduce 分析 -> 新表,我们采用 (HBase -> MapReduce 分析 -> bulkload -> 新表)方式。

demo如下:

Mapper如下:public class MyReducer extends Reducer<ImmutableBytesWritable, ImmutableBytesWritable, ImmutableBytesWritable, KeyValue> {

static Logger LOG = Logger.getLogger(MyReducer.class);

public void reduce(ImmutableBytesWritable key, Iterable<ImmutableBytesWritable> values, Context context) throws IOException, InterruptedException {
try {
context.write(key, kv);
} catch (Exception e) {
LOG.error(e);
return;
} // catch
} // reduce function

}

Reducer如下:

public class MyReducer extends Reducer<ImmutableBytesWritable, ImmutableBytesWritable, ImmutableBytesWritable, KeyValue> {

static Logger LOG = Logger.getLogger(MyReducer.class);

public void reduce(ImmutableBytesWritable key, Iterable<ImmutableBytesWritable> values, Context context) throws IOException, InterruptedException {
try {
context.write(key, kv);
} catch (Exception e) {
LOG.error(e);
return;
} // catch
} // reduce function

}


Job and BulkLoad:
public abstract class JobBulkLoad {

public void run(String[] args) throws Exception {
try {
if (args.length < 1) {
System.err.println("please set input dir");
System.exit(-1);
return;
}

String srcTableName = args[0];
String destTableName = args[1];
TableCreator.createTable(20, true, destTableName);

// 设置 HBase 参数
HBaseConfiguration conf = new HBaseConfiguration();
conf.set("hbase.zookeeper.quorum", "yp-name02,yp-name01,yp-data01");
// conf.set("hbase.zookeeper.quorum", "nn01, nn02, dn01");
conf.set("hbase.zookeeper.property.clientPort", "2181");

// 设置 Job 参数
Job job = new Job(conf, "hbase2hbase-bulkload");
job.setJarByClass(JobBulkLoad.class);
HTable htable = new HTable(conf, destTableName); // 根据region的数量来决定reduce的数量以及每个reduce覆盖的rowkey范围

// ----------------------------------------------------------------------------------------
Scan scan = new Scan();
scan.setCaching(2500);
scan.setCacheBlocks(false);
TableMapReduceUtil.initTableMapperJob(srcTableName, scan, MyMapper.class, ImmutableBytesWritable.class, ImmutableBytesWritable.class, job);
// TableMapReduceUtil.initTableReducerJob(destTableName, Common_Reducer.class, job);

job.setReducerClass(MyReducer.class);
Date now = new Date();
Path output = new Path("/output/" + destTableName + "/" + now.getTime());
System.out.println("/output/" + destTableName + "/" + now.getTime());

HFileOutputFormat.configureIncrementalLoad(job, htable);
FileOutputFormat.setOutputPath(job, output);
HFileOutputFormat.configureIncrementalLoad(job, htable);
job.waitForCompletion(true);

//----- 执行BulkLoad -------------------------------------------------------------------------------
HdfsUtil.chmod(conf, output.toString());
HdfsUtil.chmod(conf, output + "/" + YeepayConstant.COMMON_FAMILY);
htable = new HTable(conf, destTableName);
new LoadIncrementalHFiles(conf).doBulkLoad(output, htable);
System.out.println("HFile data load success!");
} catch (Throwable t) {
throw new RuntimeException(t);
}
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息