30

HBase实践|通过BulkLoad快速将海量数据导入到HBase

 3 years ago
source link: http://mp.weixin.qq.com/s?__biz=MzU5OTQ1MDEzMA%3D%3D&%3Bmid=2247488059&%3Bidx=1&%3Bsn=c4fd972c781d1dc34efd203af57cca3b
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

在第一次建立HBase表的时候,我们可能需要往里面一次性导入大量的初始化数据。我们很自然地想到将数据一条条插入到HBase中,或者通过MR方式等。但是这些方式不是慢就是在导入的过程的占用Region资源导致效率低下,所以很不适合一次性导入大量数据。本文将针对这个问题介绍如何通过HBase的BulkLoad方法来快速将海量数据导入到HBase中。

总的来说,使用 Bulk Load 方式由于利用了 HBase 的数据信息是按照特定格式存储在 HDFS 里的这一特性,直接在 HDFS 中生成持久化的 HFile 数据格式文件,然后完成巨量数据快速入库的操作,配合 MapReduce 完成这样的操作,不占用 Region 资源,不会产生巨量的写入 I/O,所以需要较少的 CPU 和网络资源。Bulk Load 的实现原理是通过一个 MapReduce Job 来实现的,通过 Job 直接生成一个 HBase 的内部 HFile 格式文件,用来形成一个特殊的 HBase 数据表,然后直接将数据文件加载到运行的集群中。与使用HBase API相比,使用Bulkload导入数据占用更少的CPU和网络资源。

实现原理

Bulkload过程主要包括三部分:

从数据源(通常是文本文件或其他的数据库)提取数据并上传到HDFS。抽取数据到HDFS和HBase并没有关系,所以大家可以选用自己擅长的方式进行,本文就不介绍了。 利用MapReduce作业处理事先准备的数据 。这一步需要一个MapReduce作业,并且大多数情况下还需要我们自己编写Map函数,而Reduce函数不需要我们考虑,由HBase提供。该作业需要使用rowkey(行键)作为输出Key;KeyValue、Put或者Delete作为输出Value。MapReduce作业需要使用HFileOutputFormat2来生成HBase数据文件。为了有效的导入数据,需要配置HFileOutputFormat2使得每一个输出文件都在一个合适的区域中。为了达到这个目的,MapReduce作业会使用Hadoop的TotalOrderPartitioner类根据表的key值将输出分割开来。HFileOutputFormat2的方法configureIncrementalLoad()会自动的完成上面的工作。 告诉RegionServers数据的位置并导入数据。这一步是最简单的,通常需要使用LoadIncrementalHFiles(更为人所熟知是completebulkload工具),将文件在HDFS上的位置传递给它,它就会利用RegionServer将数据导入到相应的区域。

整个过程图如下:

B3yMn2.png!mobile

上面我们已经介绍了HBase的BulkLoad方法的原理,我们需要写个Mapper和驱动程序,实现如下:

使用MapReduce生成HFile文件

publicclassIteblogBulkLoadMapperextendsMapper<LongWritable,Text,ImmutableBytesWritable,Put>{

protectedvoid map(LongWritable key,Text value,Context context)throwsIOException,InterruptedException{

String line = value.toString();

String[] items = line.split("\t");

ImmutableBytesWritable rowKey =newImmutableBytesWritable(items[0].getBytes());

Put put =newPut(Bytes.toBytes(items[0]));//ROWKEY

put.addColumn("f1".getBytes(),"url".getBytes(), items[1].getBytes());

put.addColumn("f1".getBytes(),"name".getBytes(), items[2].getBytes());

context.write(rowkey, put);

}

}

驱动程序

publicclassIteblogBulkLoadDriver{

publicstaticvoid main(String[] args)throwsIOException,ClassNotFoundException,InterruptedException{

finalString SRC_PATH="hdfs://iteblog:9000/user/iteblog/input";

finalString DESC_PATH="hdfs://iteblog:9000/user/iteblog/output";

Configuration conf =HBaseConfiguration.create();

Job job=Job.getInstance(conf);

job.setJarByClass(IteblogBulkLoadDriver.class);

job.setMapperClass(IteblogBulkLoadMapper.class);

job.setMapOutputKeyClass(ImmutableBytesWritable.class);

job.setMapOutputValueClass(Put.class);

job.setOutputFormatClass(HFileOutputFormat2.class);

HTable table =newHTable(conf,"blog_info");

HFileOutputFormat2.configureIncrementalLoad(job,table,table.getRegionLocator());

FileInputFormat.addInputPath(job,newPath(SRC_PATH));

FileOutputFormat.setOutputPath(job,newPath(DESC_PATH));

System.exit(job.waitForCompletion(true)?0:1);

}

}

通过BlukLoad方式加载HFile文件

publicclassLoadIncrementalHFileToHBase{

publicstaticvoid main(String[] args)throwsException{

Configuration configuration =HBaseConfiguration.create();

HBaseConfiguration.addHbaseResources(configuration);

LoadIncrementalHFiles loder =newLoadIncrementalHFiles(configuration);

HTable hTable =newHTable(configuration,"blog_info");

loder.doBulkLoad(newPath("hdfs://iteblog:9000/user/iteblog/output"), hTable);

}

}

由于HBase的BulkLoad方式是绕过了Write to WAL,Write to MemStore及Flush to disk的过程,所以并不能通过WAL来进行一些复制数据的操作。后面我将会再介绍如何通过Spark来使用Hbase的BulkLoad方式来初始化数据。

BulkLoad的使用案例

首次将原始数据集载入 HBase- 您的初始数据集可能很大,绕过 HBase 写入路径可以显著加速此进程。 递增负载 - 要定期加载新数据,请使用 BulkLoad 并按照自己的理想时间间隔分批次导入数据。这可以缓解延迟问题,并且有助于您实现服务级别协议 (SLA)。但是,压缩触发器就是 RegionServer 上的 HFile 数目。因此,频繁导入大量 HFile 可能会导致更频繁地发生大型压缩,从而对性能产生负面影响。您可以通过以下方法缓解此问题:调整压缩设置,确保不触发压缩即可存在的最大 HFile 文件数很高,并依赖于其他因素,如 Memstore 的大小 触发压缩。 数据需要源于其他位置 - 如果当前系统捕获了您想在 HBase 中包含的数据,且因业务原因需要保持活动状态,您可从系统中将数据定期批量加载到 HBase 中,以便可以在不影响系统的前提下对其执行操作。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK