简述HBase的Bulk Load
为什么用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的更多相关文章
- 【hbase】——bulk load导入数据时value=\x00\x00\x00\x01问题解析
一.存入数据类型 Hbase里面,rowkey是按照字典序进行排序.存储的value值,当用filter进行数据筛选的时候,所用的比较算法也是字典序的. 1.当存储的value值是float类型的时候 ...
- Bulk Load-HBase数据导入最佳实践
一.概述 HBase本身提供了非常多种数据导入的方式,通常有两种经常使用方式: 1.使用HBase提供的TableOutputFormat,原理是通过一个Mapreduce作业将数据导入HBase 2 ...
- 图解JanusGraph系列 - 关于JanusGraph图数据批量快速导入的方案和想法(bulk load data)
大家好,我是洋仔,JanusGraph图解系列文章,实时更新~ 图数据库文章总目录: 整理所有图相关文章,请移步(超链):图数据库系列-文章总目录 源码分析相关可查看github(码文不易,求个sta ...
- MySQL Backup--xtrabackup与Bulk Load for Create Index
场景描述:主从使用MySQL 5.7.19 1.从库上使用xtrabackup进行热备. 2.主库行执行DDL创建索引: ALTER TABLE `tb_xxx` ADD INDEX idx_good ...
- Spark写入HBase(Bulk方式)
在使用Spark时经常需要把数据落入HBase中,如果使用普通的Java API,写入会速度很慢.还好Spark提供了Bulk写入方式的接口.那么Bulk写入与普通写入相比有什么优势呢? BulkLo ...
- Using SQLXML Bulk Load in the .NET Environment
http://msdn.microsoft.com/en-us/library/ms171878.aspx 1.首先创建一张表 CREATE TABLE Ord ( OrderID ,) PRIMAR ...
- 【hbase】——HBase 写优化之 BulkLoad 实现数据快速入库
1.为何要 BulkLoad 导入?传统的 HTableOutputFormat 写 HBase 有什么问题? 我们先看下 HBase 的写流程: 通常 MapReduce 在写HBase时使用的是 ...
- hbase运行mapreduce设置及基本数据加载方法
hbase与mapreduce集成后,运行mapreduce程序,同时需要mapreduce jar和hbase jar文件的支持,这时我们需要通过特殊设置使任务可以同时读取到hadoop jar和h ...
- 批量导入数据到HBase
hbase一般用于大数据的批量分析,所以在很多情况下需要将大量数据从外部导入到hbase中,hbase提供了一种导入数据的方式,主要用于批量导入大量数据,即importtsv工具,用法如下: Us ...
随机推荐
- 02_Linux实操篇
第五章 VI和VIM编辑器 5.1. VI和VIM基本介绍 Vi编辑器是所有Unix及Linux系统下标准的编辑器,它的强大不逊色于任何最新的文本编辑器.由于对Unix及Linux系统的任何版本,Vi ...
- Python File write() 方法
概述 write() 方法用于向文件中写入指定字符串.高佣联盟 www.cgewang.com 在文件关闭前或缓冲区刷新前,字符串内容存储在缓冲区中,这时你在文件中是看不到写入的内容的. 如果文件打开 ...
- 当asp.net core偶遇docker一(模型验证和Rabbitmq 三)
继续上一篇 上一篇,从core方式实现了一个Rabbitmq发送队列消息的接口,我们现在需要在模型验证里面加入验证失败就发送消息的部分 [AttributeUsage(AttributeTargets ...
- SLAM中的逆深度参数化
参数化问题 在SLAM的建图过程中,把像素深度假设成了高斯分布.那么这么假设是否是合适的呢?这里关系到一个参数化的问题. 我们经常用一个点的世界坐标x,y,z三个量来描述它,这是一种参数化形式.我们认 ...
- alpine 容器优化
摘要:alpine容器一直是使用得比较多的,而且也是官方推荐使用的.但是官方的容器会有一些不方便的地方,比如安装软件, 时区不同等. 所以本文旨在完成一个alpine容器通用模板作为记录 # 导入 ...
- JavaScript按位运算符~
1. JavaScript按位运算符 Bit operators work on 32 bits numbers. 2. JavaScript按位运算符~ 值得注意的是,在JavaScript中,~5 ...
- 树莓派4B的CPU系统里查到为BCM2835而非BCM2711
树莓派4B采用四核64位的ARM Cortex-A72架构CPU,型号为博通BCM2711 SoC.2711是个64位的四核,而2835是多年前的32位单核CPU. 查看当前芯片版本,显示为4核心,但 ...
- klassVtable与klassItable
klassVtable与klassItable类用来实现Java方法的多态,也可以叫动态绑定,是指在应用执行期间通过判断接受对象的实际类型,根据实际类型调用对应的方法.C++为了实现多态,在对象中嵌入 ...
- 【API进阶之路】无法想象!大龄码农的硬盘里有这么多宝藏
摘要:通过把所需建立的工具库做成云容器化应用,用CCE引擎,通过API网关调用云容器引擎中的容器应用.不仅顺应了云原生的发展趋势,还能随时弹性扩容,满足公司规模化发展的需求. 公司开完年中会后,大家的 ...
- C#LeetCode刷题之#653-两数之和 IV - 输入 BST(Two Sum IV - Input is a BST)
问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/4098 访问. 给定一个二叉搜索树和一个目标结果,如果 BST 中 ...