为什么用Bulk load?

批量加载数据到HBase集群,有很多种方式,比如利用 HBase API 进行批量写入数据、使用Sqoop工具批量导数到HBase集群、使用MapReduce批量导入等等,但是这些方法都有一个问题:导入数据的过程如果数据量过大,可能耗时会比较严重或者占用HBase集群资源较多(如磁盘IO、HBase Handler数等)

使用 HBase BulkLoad的方式来进行海量数据批量写入到HBase集群,可以对大数据量的情况下做一些优化,提高性能。

在使用BulkLoad之前,我们先来了解一下HBase的存储机制。HBase存储数据其底层使用的是HDFS来作为存储介质,HBase的每一张表对应的HDFS目录上的一个文件夹,文件夹名以HBase表进行命名(如果没有使用命名空间,则默认在default目录下),在表文件夹下存放在若干个Region命名的文件夹,Region文件夹中的每个列簇也是用文件夹进行存储的,每个列簇中存储就是实际的数据,以HFile的形式存在,路径格式如下:

/hbase/data/default/<tbl_name>/<region_id>/<cf>/<hfile_id>

实现原理

按照HBase存储数据按照HFile格式存储在HDFS的原理,使用MapReduce直接生成HFile格式的数据文件,然后在通过RegionServer将HFile数据文件移动到相应的Region上面,实现流程如图所示:

生成HFile文件

HFile文件的生成,可以使用MapReduce来进行实现,将数据源准备好,上传到HDFS进行存储,然后在程序中读取HDFS上的数据源,进行自定义封装,组装RowKey,然后将封装后的数据在回写到HDFS上,以HFile的形式存储到HDFS指定的目录中。实现代码:

public class GemeratorHFile2 {
static class HFileImportMapper2 extends Mapper<LongWritable, Text, ImmutableBytesWritable, KeyValue> { protected final String CF_KQ = "cf"; @Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
String line = value.toString();
System.out.println("line : " + line);
String[] datas = line.split(" ");
String row = new Date().getTime() + "_" + datas[1];
ImmutableBytesWritable rowkey = new ImmutableBytesWritable(Bytes.toBytes(row));
KeyValue kv = new KeyValue(Bytes.toBytes(row), this.CF_KQ.getBytes(), datas[1].getBytes(), datas[2].getBytes());
context.write(rowkey, kv);
}
} public static void main(String[] args) {
if (args.length != 1) {
System.out.println("<Usage>Please input hbase-site.xml path.</Usage>");
return;
}
Configuration conf = new Configuration();
conf.addResource(new Path(args[0]));
conf.set("hbase.fs.tmp.dir", "partitions_" + UUID.randomUUID());
String tableName = "person";
String input = "hdfs://nna:9000/tmp/person.txt";
String output = "hdfs://nna:9000/tmp/pres";
System.out.println("table : " + tableName);
HTable table;
try {
try {
FileSystem fs = FileSystem.get(URI.create(output), conf);
fs.delete(new Path(output), true);
fs.close();
} catch (IOException e1) {
e1.printStackTrace();
} Connection conn = ConnectionFactory.createConnection(conf);
table = (HTable) conn.getTable(TableName.valueOf(tableName));
Job job = Job.getInstance(conf);
job.setJobName("Generate HFile"); job.setJarByClass(GemeratorHFile2.class);
job.setInputFormatClass(TextInputFormat.class);
job.setMapperClass(HFileImportMapper2.class);
FileInputFormat.setInputPaths(job, input);
FileOutputFormat.setOutputPath(job, new Path(output)); HFileOutputFormat2.configureIncrementalLoad(job, table);
try {
job.waitForCompletion(true);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
} }
}

在HDFS目录/tmp/person.txt中,准备数据源如下:

1 smartloli 100
2 smartloli2 101
3 smartloli3 102

然后将上述代码编译打包成jar,上传到Hadoop集群进行执行,执行以下命令:

hadoop jar GemeratorHFile2.jar /data/soft/new/apps/hbaseapp/hbase-site.xml

如果在执行命令的过程中,出现找不到类的异常信息,可能是本地没有加载HBase依赖jar包,当前用户配置如下环境变量信息:

export HADOOP_CLASSPATH=$HBASE_HOME/lib/*:classpath

然后执行source命令使配置的内容立即生效。

执行预览

成功提交任务Linux控制台打印执行任务进度,也可以到YARN的资源监控界面查看执行进度,结果如图所示:

等待任务的执行,执行完成后在对应HDFS路径上会生成相应的HFile数据文件,如图所示:

使用BulkLoad导入到HBase

使用BulkLoad的方式将生成的HFile文件导入到HBase集群中,这里有两种导入方式。一种是写代码实现导入,另一种是使用HBase命令进行导入。

写代码实现导入

通过LoadIncrementalHFiles类来实现导入,具体代码:

public class BulkLoad2HBase {

    public static void main(String[] args) throws Exception {
if (args.length != 1) {
System.out.println("<Usage>Please input hbase-site.xml path.</Usage>");
return;
}
String output = "hdfs://cluster1/tmp/pres";
Configuration conf = new Configuration();
conf.addResource(new Path(args[0]));
HTable table = new HTable(conf, "person");
LoadIncrementalHFiles loader = new LoadIncrementalHFiles(conf);
loader.doBulkLoad(new Path(output), table);
} }

执行上述代码运行结果:

使用HBase命令进行导入

先将生成好的HFile文件迁移到目标集群(即HBase集群所在的HDFS上),然后使用HBase命令进行导入,执行以下命令:

# 先使用distcp迁移hfile
hadoop distcp -Dmapreduce.job.queuename=queue_1024_01 -update -skipcrccheck -m 10 /tmp/pres hdfs://nns:9000/tmp/pres
# 使用bulkload方式导入数据
hbase org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles /tmp/pres person

最后,我们可以到指定的RegionServer节点上查看导入的日志信息,导入成功的日志信息:

2018-08-19 16:30:34,969 INFO  [B.defaultRpcServer.handler=7,queue=1,port=16020] regionserver.HStore: Successfully loaded store file hdfs://cluster1/tmp/pres/cf/7b455535f660444695589edf509935e9 into store cf (new location: hdfs://cluster1/hbase/data/default/person/2d7483d4abd6d20acdf16533a3fdf18f/cf/d72c8846327d42e2a00780ac2facf95b_SeqId_4_)

2.5 验证

使用BulkLoad方式导入数据后,可以进入到HBase集群,使用HBase Shell来查看数据是否导入成功,预览结果如图所示:

总结

本篇文章为了演示实战效果,将生成HFile文件和使用BulkLoad方式导入HFile到HBase集群的步骤进行分解,实际情况可以将这两个步骤合并为一个,实现自动化生成与HFile自动导入。如果在执行的过程中出现RpcRetryingCaller的异常,可以到对应RegionServer节点查看日志信息,这里面记录出现这种异常的详细原因。

简述HBase的Bulk Load的更多相关文章

  1. 【hbase】——bulk load导入数据时value=\x00\x00\x00\x01问题解析

    一.存入数据类型 Hbase里面,rowkey是按照字典序进行排序.存储的value值,当用filter进行数据筛选的时候,所用的比较算法也是字典序的. 1.当存储的value值是float类型的时候 ...

  2. Bulk Load-HBase数据导入最佳实践

    一.概述 HBase本身提供了非常多种数据导入的方式,通常有两种经常使用方式: 1.使用HBase提供的TableOutputFormat,原理是通过一个Mapreduce作业将数据导入HBase 2 ...

  3. 图解JanusGraph系列 - 关于JanusGraph图数据批量快速导入的方案和想法(bulk load data)

    大家好,我是洋仔,JanusGraph图解系列文章,实时更新~ 图数据库文章总目录: 整理所有图相关文章,请移步(超链):图数据库系列-文章总目录 源码分析相关可查看github(码文不易,求个sta ...

  4. MySQL Backup--xtrabackup与Bulk Load for Create Index

    场景描述:主从使用MySQL 5.7.19 1.从库上使用xtrabackup进行热备. 2.主库行执行DDL创建索引: ALTER TABLE `tb_xxx` ADD INDEX idx_good ...

  5. Spark写入HBase(Bulk方式)

    在使用Spark时经常需要把数据落入HBase中,如果使用普通的Java API,写入会速度很慢.还好Spark提供了Bulk写入方式的接口.那么Bulk写入与普通写入相比有什么优势呢? BulkLo ...

  6. Using SQLXML Bulk Load in the .NET Environment

    http://msdn.microsoft.com/en-us/library/ms171878.aspx 1.首先创建一张表 CREATE TABLE Ord ( OrderID ,) PRIMAR ...

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

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

  8. hbase运行mapreduce设置及基本数据加载方法

    hbase与mapreduce集成后,运行mapreduce程序,同时需要mapreduce jar和hbase jar文件的支持,这时我们需要通过特殊设置使任务可以同时读取到hadoop jar和h ...

  9. 批量导入数据到HBase

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

随机推荐

  1. Day13_Thymeleaf简介

    学于黑马和传智播客联合做的教学项目 感谢 黑马官网 传智播客官网 微信搜索"艺术行者",关注并回复关键词"乐优商城"获取视频和教程资料! b站在线视频 1.Th ...

  2. JavaScript高级程序设计(第三版) 5/25

    第三章 基本概念 1.任何语言的核心都必然会描述这门语言最基本的工作原理.而描述的内容通常都要涉及这门语言的语法.操作符.数据类型.内置功能等用于构建复杂解决方案的基本概念. 2.浮点数值,该数值中必 ...

  3. IPython magic命令

  4. Python 数字类型转换

    Python数字类型转换: int(x):将 x 转换为一个整数 float(x):将 x 转换为一个浮点数 complex(x,y):将 x 和 y 转换为一个复数.x 为复数的实部,y 为复数的虚 ...

  5. PHP rsort() 函数

    实例 对数组 $cars 中的元素按字母进行降序排序: <?php$cars=array("Volvo","BMW","Toyota" ...

  6. 用大白话的方式讲明白Java的StringBuilder、StringBuffer的扩容机制

    StringBuffer和StringBuilder,它们的底层char数组value默认的初始化容量是16,扩容只需要修改底层的char数组,两者的扩容最终都会调用到AbstractStringBu ...

  7. 连接云MariaDB实例

    新建实例 MariaDB CVM 内网连接 CVM远程登录测试(同一个VPC下): CVM安装客户端: yum install mysql 连接: mysql -h MariaDB内网ip -u 数据 ...

  8. ubuntu16.04下chrome安装flash插件

    最近自己的ubuntu安装了最新的chrome54版本,发现视频无法播放,提示flash版本过期,原来最新的chrome已经不内置flash插件了,需要自己安装. 方法/步骤 1.安装chrome打开 ...

  9. 通过源码分析Java开源任务调度框架Quartz的主要流程

    通过源码分析Java开源任务调度框架Quartz的主要流程 从使用效果.调用链路跟踪.E-R图.循环调度逻辑几个方面分析Quartz. github项目地址: https://github.com/t ...

  10. Pytest单元测试框架-学习

    pytest: Python的一个单元测试框架,基于UnitTest二次开发,语法上更加简洁,可以用来做Python开发项目的单元测试,UI自动化.接口自动化测试等,有很多的插件访问Pytest插件汇 ...