Apache HBase是一个分布式的、面向列的开源数据库。它能够让我们随机的、实时的訪问大数据。可是如何有效的将数据导入到HBase呢?HBase有多种导入数据的方法。最直接的方法就是在MapReduce作业中使用TableOutputFormat作为输出。或者使用标准的客户端API,可是这些都不是很有效的方法。

Bulkload利用MapReduce作业输出HBase内部数据格式的表数据,然后将生成的StoreFiles直接导入到集群中。

与使用HBase API相比,使用Bulkload导入数据占用更少的CPU和网络资源。

Bulkload过程主要包含三部分:

1.从数据源(一般是文本文件或其它的数据库)提取数据并上传到HDFS

这一步不在HBase的考虑范围内,无论数据源是什么,仅仅要在进行下一步之前将数据上传到HDFS就可以。

2.利用一个MapReduce作业准备数据

这一步须要一个MapReduce作业。而且大多数情况下还须要我们自己编写Map函数,而Reduce函数不须要我们考虑。由HBase提供。

该作业须要使用rowkey(行键)作为输出Key,KeyValue、Put或者Delete作为输出Value。MapReduce作业须要使用HFileOutputFormat2来生成HBase数据文件。为了有效的导入数据,须要配置HFileOutputFormat2使得每个输出文件都在一个合适的区域中。为了达到这个目的,MapReduce作业会使用Hadoop的TotalOrderPartitioner类依据表的key值将输出切割开来。

HFileOutputFormat2的方法configureIncrementalLoad()会自己主动的完毕上面的工作。

3.告诉RegionServers数据的位置并导入数据

这一步是最简单的,通常须要使用LoadIncrementalHFiles(更为人所熟知是completebulkload工具)。将文件在HDFS上的位置传递给它,它就会利用RegionServer将数据导入到对应的区域。

下图简单明白的说明了整个过程

图片来自How-to: Use HBase Bulk Loading, and Why

Note:在进行BulkLoad之前,要在HBase中创建与程序中同名且结构同样的空表

Java实现例如以下:

BulkLoadDriver.java

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.mapreduce.HFileOutputFormat2;
import org.apache.hadoop.mapreduce.Job;
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.Tool;
import org.apache.hadoop.util.ToolRunner; /**
* Created by shaobo on 15-6-9.
*/
public class BulkLoadDriver extends Configured implements Tool {
private static final String DATA_SEPERATOR = "\\s+";
private static final String TABLE_NAME = "temperature";//表名
private static final String COLUMN_FAMILY_1="date";//列组1
private static final String COLUMN_FAMILY_2="tempPerHour";//列组2 public static void main(String[] args) {
try {
int response = ToolRunner.run(HBaseConfiguration.create(), new BulkLoadDriver(), args);
if(response == 0) {
System.out.println("Job is successfully completed...");
} else {
System.out.println("Job failed...");
}
} catch(Exception exception) {
exception.printStackTrace();
}
} public int run(String[] args) throws Exception {
String outputPath = args[1];
/**
* 设置作业參数
*/
Configuration configuration = getConf();
configuration.set("data.seperator", DATA_SEPERATOR);
configuration.set("hbase.table.name", TABLE_NAME);
configuration.set("COLUMN_FAMILY_1", COLUMN_FAMILY_1);
configuration.set("COLUMN_FAMILY_2", COLUMN_FAMILY_2);
Job job = Job.getInstance(configuration, "Bulk Loading HBase Table::" + TABLE_NAME);
job.setJarByClass(BulkLoadDriver.class);
job.setInputFormatClass(TextInputFormat.class);
job.setMapOutputKeyClass(ImmutableBytesWritable.class);//指定输出键类
job.setMapOutputValueClass(Put.class);//指定输出值类
job.setMapperClass(BulkLoadMapper.class);//指定Map函数
FileInputFormat.addInputPaths(job, args[0]);//输入路径
FileSystem fs = FileSystem.get(configuration);
Path output = new Path(outputPath);
if (fs.exists(output)) {
fs.delete(output, true);//假设输出路径存在,就将其删除
}
FileOutputFormat.setOutputPath(job, output);//输出路径
Connection connection = ConnectionFactory.createConnection(configuration);
TableName tableName = TableName.valueOf(TABLE_NAME);
HFileOutputFormat2.configureIncrementalLoad(job, connection.getTable(tableName), connection.getRegionLocator(tableName));
job.waitForCompletion(true);
if (job.isSuccessful()){
HFileLoader.doBulkLoad(outputPath, TABLE_NAME);//导入数据
return 0;
} else {
return 1;
}
} }

BulkLoadMapper.java

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper; /**
* Created by shaobo on 15-6-9.
*/
public class BulkLoadMapper extends Mapper<LongWritable, Text, ImmutableBytesWritable, Put> {
private String hbaseTable;
private String dataSeperator;
private String columnFamily1;
private String columnFamily2; public void setup(Context context) {
Configuration configuration = context.getConfiguration();//获取作业參数
hbaseTable = configuration.get("hbase.table.name");
dataSeperator = configuration.get("data.seperator");
columnFamily1 = configuration.get("COLUMN_FAMILY_1");
columnFamily2 = configuration.get("COLUMN_FAMILY_2");
} public void map(LongWritable key, Text value, Context context){
try {
String[] values = value.toString().split(dataSeperator);
ImmutableBytesWritable rowKey = new ImmutableBytesWritable(values[0].getBytes());
Put put = new Put(Bytes.toBytes(values[0]));
put.addColumn(Bytes.toBytes(columnFamily1), Bytes.toBytes("month"), Bytes.toBytes(values[1]));
put.addColumn(Bytes.toBytes(columnFamily1), Bytes.toBytes("day"), Bytes.toBytes(values[2]));
for (int i = 3; i < values.length; ++i){
put.addColumn(Bytes.toBytes(columnFamily2), Bytes.toBytes("hour : " + i), Bytes.toBytes(values[i]));
}
context.write(rowKey, put);
} catch(Exception exception) {
exception.printStackTrace();
} } }

HFileLoader.java

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles; /**
* Created by shaobo on 15-6-9.
*/
public class HFileLoader {
public static void doBulkLoad(String pathToHFile, String tableName){
try {
Configuration configuration = new Configuration();
HBaseConfiguration.addHbaseResources(configuration);
LoadIncrementalHFiles loadFfiles = new LoadIncrementalHFiles(configuration);
HTable hTable = new HTable(configuration, tableName);//指定表名
loadFfiles.doBulkLoad(new Path(pathToHFile), hTable);//导入数据
System.out.println("Bulk Load Completed..");
} catch(Exception exception) {
exception.printStackTrace();
} } }

将程序编译打包,提交到Hadoop执行

HADOOP_CLASSPATH=$(hbase mapredcp):/path/to/hbase/conf hadoop jar BulkLoad.jar inputpath outputpath

上述命令使用方法可參考44. HBase, MapReduce, and the CLASSPATH

作业执行情况:

15/06/14 14:31:07 INFO mapreduce.HFileOutputFormat2: Looking up current regions for table temperature(表名)
15/06/14 14:31:07 INFO mapreduce.HFileOutputFormat2: Configuring 1 reduce partitions to match current region count
15/06/14 14:31:07 INFO mapreduce.HFileOutputFormat2: Writing partition information to /home/shaobo/hadoop/tmp/partitions_5d464f1e-d412-4dbe-bb98-367f8431bdc9
15/06/14 14:31:07 INFO zlib.ZlibFactory: Successfully loaded & initialized native-zlib library
15/06/14 14:31:07 INFO compress.CodecPool: Got brand-new compressor [.deflate]
15/06/14 14:31:08 INFO mapreduce.HFileOutputFormat2: Incremental table temperature(表名) output configured.
15/06/14 14:31:08 INFO client.RMProxy: Connecting to ResourceManager at localhost/127.0.0.1:8032
15/06/14 14:31:15 INFO input.FileInputFormat: Total input paths to process : 2
15/06/14 14:31:15 INFO mapreduce.JobSubmitter: number of splits:2
15/06/14 14:31:16 INFO mapreduce.JobSubmitter: Submitting tokens for job: job_1434262360688_0002
15/06/14 14:31:17 INFO impl.YarnClientImpl: Submitted application application_1434262360688_0002
15/06/14 14:31:17 INFO mapreduce.Job: The url to track the job: http://shaobo-ThinkPad-E420:8088/proxy/application_1434262360688_0002/
15/06/14 14:31:17 INFO mapreduce.Job: Running job: job_1434262360688_0002
15/06/14 14:31:28 INFO mapreduce.Job: Job job_1434262360688_0002 running in uber mode : false
15/06/14 14:31:28 INFO mapreduce.Job: map 0% reduce 0%
15/06/14 14:32:24 INFO mapreduce.Job: map 49% reduce 0%
15/06/14 14:32:37 INFO mapreduce.Job: map 67% reduce 0%
15/06/14 14:32:43 INFO mapreduce.Job: map 100% reduce 0%
15/06/14 14:33:39 INFO mapreduce.Job: map 100% reduce 67%
15/06/14 14:33:42 INFO mapreduce.Job: map 100% reduce 70%
15/06/14 14:33:45 INFO mapreduce.Job: map 100% reduce 88%
15/06/14 14:33:48 INFO mapreduce.Job: map 100% reduce 100%
15/06/14 14:33:52 INFO mapreduce.Job: Job job_1434262360688_0002 completed successfully
...
...
...
15/06/14 14:34:02 WARN mapreduce.LoadIncrementalHFiles: Skipping non-directory hdfs://localhost:9000/user/output/_SUCCESS
15/06/14 14:34:03 INFO hfile.CacheConfig: CacheConfig:disabled
15/06/14 14:34:03 INFO hfile.CacheConfig: CacheConfig:disabled
15/06/14 14:34:07 INFO mapreduce.LoadIncrementalHFiles: Trying to load hfile=hdfs://localhost:9000/user/output/date/c64cd2524fba48738bab26630d550b61 first=AQW00061705 last=USW00094910
15/06/14 14:34:07 INFO mapreduce.LoadIncrementalHFiles: Trying to load hfile=hdfs://localhost:9000/user/output/tempPerHour/43af29456913444795a820544691eb3d first=AQW00061705 last=USW00094910
Bulk Load Completed..
Job is successfully completed...

BulLoad过程的第三步也能够在用MapReduce作业生成HBase数据文件后在命令行中进行,不一定要与MapReduce过程写在一起。

$ hadoop jar hbase-server-VERSION.jar completebulkload [-c /path/to/hbase/config/hbase-site.xml] outputpath tablename

若在提交作业是产生例如以下异常:

15/06/16 11:41:06 INFO mapreduce.Job: Job job_1434420992867_0003 failed with state FAILED due to: Application application_1434420992867_0003 failed 2 times due to AM Container for appattempt_1434420992867_0003_000002 exited with  exitCode: -1000
For more detailed output, check application tracking page:http://cdh1:8088/proxy/application_1434420992867_0003/Then, click on links to logs of each attempt.
Diagnostics: Rename cannot overwrite non empty destination directory /data/yarn/nm/usercache/hdfs/filecache/16
java.io.IOException: Rename cannot overwrite non empty destination directory /data/yarn/nm/usercache/hdfs/filecache/16
at org.apache.hadoop.fs.AbstractFileSystem.renameInternal(AbstractFileSystem.java:716)
at org.apache.hadoop.fs.FilterFs.renameInternal(FilterFs.java:228)
at org.apache.hadoop.fs.AbstractFileSystem.rename(AbstractFileSystem.java:659)
at org.apache.hadoop.fs.FileContext.rename(FileContext.java:909)
at org.apache.hadoop.yarn.util.FSDownload.call(FSDownload.java:364)
at org.apache.hadoop.yarn.util.FSDownload.call(FSDownload.java:60)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745) Failing this attempt. Failing the application.
15/06/16 11:41:06 INFO mapreduce.Job: Counters: 0

将cdh2和cdh3机器的/data/yarn/nm/usercache/hdfs/filecache下的文件删除就可以。可參考http://stackoverflow.com/questions/30857413/hadoop-complains-about-attempting-to-overwrite-nonempty-destination-directory

參考资料:

http://hbase.apache.org/book.html#arch.bulk.load

http://blog.cloudera.com/blog/2013/09/how-to-use-hbase-bulk-loading-and-why/

HBase高速导入数据--BulkLoad的更多相关文章

  1. SQL Server高速导入数据分享

    SQL Server高速导入数据,能够尝试的方法例如以下:CTE.OpenRowSet/OpenDataSource.BULK INSERT.bcp.Shell. 以下依次介绍这几种办法. 1.CTE ...

  2. Hbase 学习(十一)使用hive往hbase当中导入数据

    我们可以有很多方式可以把数据导入到hbase当中,比如说用map-reduce,使用TableOutputFormat这个类,但是这种方式不是最优的方式. Bulk的方式直接生成HFiles,写入到文 ...

  3. 大数据学习笔记——HBase使用bulkload导入数据

    HBase使用bulkload批量导入数据 HBase可使用put命令向一张已经建好了的表中插入数据,然而,当遇到数据量非常大的情况,一条一条的进行插入效率将会大大降低,因此本篇博客将会整理提高批量导 ...

  4. 【hbase】——HBase 写优化之 BulkLoad 实现数据快速入库

    1.为何要 BulkLoad 导入?传统的 HTableOutputFormat 写 HBase 有什么问题? 我们先看下 HBase 的写流程: 通常 MapReduce 在写HBase时使用的是 ...

  5. 批量导入数据到HBase

    hbase一般用于大数据的批量分析,所以在很多情况下需要将大量数据从外部导入到hbase中,hbase提供了一种导入数据的方式,主要用于批量导入大量数据,即importtsv工具,用法如下:   Us ...

  6. HBase 写优化之 BulkLoad 实现数据快速入库

    在第一次建立Hbase表的时候,我们可能需要往里面一次性导入大量的初始化数据.我们很自然地想到将数据一条条插入到Hbase中,或者通过MR方式等.但是这些方式不是慢就是在导入的过程的占用Region资 ...

  7. 使用Sqoop从MySQL导入数据到Hive和HBase 及近期感悟

    使用Sqoop从MySQL导入数据到Hive和HBase 及近期感悟 Sqoop 大数据 Hive HBase ETL 使用Sqoop从MySQL导入数据到Hive和HBase 及近期感悟 基础环境 ...

  8. sqoop:mysql和Hbase/Hive/Hdfs之间相互导入数据

    1.安装sqoop 请参考http://www.cnblogs.com/Richardzhu/p/3322635.html 增加了SQOOP_HOME相关环境变量:source ~/.bashrc  ...

  9. 教程 | 使用Sqoop从MySQL导入数据到Hive和HBase

    基础环境 sqoop:sqoop-1.4.5+cdh5.3.6+78, hive:hive-0.13.1+cdh5.3.6+397, hbase:hbase-0.98.6+cdh5.3.6+115 S ...

随机推荐

  1. Python学习笔记(5)--数据结构之字典dict

    字典(dict) 定义:键值对集合 初始化:{}, {'1' : 'abc', '2' : 'def'} 1.增加:单个数据直接赋值  update(dict2) ---把dict2的元素加入到dic ...

  2. 洛谷 P2440 木材加工

    P2440 木材加工 题目背景 要保护环境 题目描述 题目描述: 木材厂有一些原木,现在想把这些木头切割成一些长度相同的小段木头(木头有可能有 剩余),需要得到的小段的数目是给定的.当然,我们希望得到 ...

  3. 最全面的AndroidStudio配置指南总结-包括护眼模式

    使用AndroidStudio开发APP已有半年多的时间了,从刚开始的不习惯到慢慢适应再到逐渐喜欢上AndroidStudio,中间的过程颇有一番曲折,现在把自己对AndroidStudio的配置心得 ...

  4. C++刷题——2802: 推断字符串是否为回文

    Description 编敲代码,推断输入的一个字符串是否为回文. 若是则输出"Yes".否则输出"No". 所谓回文是指順读和倒读都是一样的字符串. Inpu ...

  5. 算法导论————EXKMP

    [例题传送门:caioj1461] [EXKMP]最长共同前缀长度 [题意]给出模板串A和子串B,长度分别为lenA和lenB,要求在线性时间内,对于每个A[i](1<=i<=lenA), ...

  6. POJ 3181完全背包(+高精)

    思路: f[i]表示还剩i空间的方案数 套个高精 (网上有人把它拆成了两个long long) 其实这道题的高精并不难写-.. //By SiriusRen #include <cstdio&g ...

  7. PowerDesigner删除外键关系,而不删除外键列[转] 及编码格式

    PowerDesigner删除外键关系,而不删除外键列[转]  数据库 database  -> generate database ->format 设置为utf-8 PowerDesi ...

  8. tensorflow学习之路----保存和提取数据

    #保存数据注意他只能保存变量,不能保存神经网络的框架.#保存数据的作用:保存权重有利于下一次的训练,或者可以用这个数据进行识别#np.arange():arange函数用于创建等差数组,使用频率非常高 ...

  9. 【Docker构建私有仓库】

    Docker默认不允许非HTTPS方式推送镜像,我们可以通过Docker的配置选项来取消此限制: [root@fedora ~]# cat /etc/docker/daemon.json { &quo ...

  10. CentOS桥接网卡配置

    网桥方式配置步骤 1.增加网桥设备br0 vi /etc/sysconfig/network-scripts/ifcfg-br0 DEVICE=br0 ONBOOT=yes TYPE=Bridge B ...