批量加载HBase数据并生成本地二级索引
操作场景
在HBase数据导入场景中,当需要将大量结构化数据(如CSV文件、日志文件)批量导入HBase时,传统的Put方式逐条写入效率低下,无法满足大规模数据导入的性能要求。同时,如果业务需要对非RowKey列进行高效查询,还需要在数据导入时同步生成本地二级索引。如何在保证数据导入性能的同时,自动完成索引数据的生成?HIndexImportTsv工具正是为解决这一问题而设计的。该工具继承了HBase批量加载数据工具ImportTsv的所有功能,支持将HDFS中的结构化数据批量转换为HFile格式并加载到HBase表中,同时在数据导入过程中自动生成本地二级索引数据,实现数据导入与索引构建的一体化操作,大幅提升大规模数据导入的效率。本文介绍如何使用HIndexImportTsv工具批量加载HBase数据并生成本地二级索引。
HBase本身提供了ImportTsv&LoadIncremental工具来批量加载用户数据。当前提供了HIndexImportTsv来支持加载用户数据的同时可以完成对索引数据的批量加载。HIndexImportTsv继承了HBase批量加载数据工具ImportTsv的所有功能。此外,如果在执行HIndexImportTsv工具之前未建表,直接运行该工具,将会在创建表时创建索引,并在生成用户数据的同时生成索引数据。
- 本地二级索引(Local Secondary Index,LSI):HBase提供的索引功能,索引数据与主表数据存储在同一Region中,索引的RowKey包含主表的RowKey。本地二级索引适合读多写少的场景,查询时可以直接从索引定位到主表数据。
- BulkLoad:HBase的批量数据加载机制,通过将数据预先转换为HFile格式(HBase的底层存储格式),然后直接将HFile文件移动到HBase的存储目录中,避免通过Write Ahead Log和MemStore的写入路径,大幅提升数据导入性能。
- HFile:HBase的底层存储文件格式,采用LSM-Tree结构,数据按RowKey有序排列。HFile支持压缩、编码等优化,是HBase高效读写的基础。
前提条件
- 已安装客户端,具体请参考安装客户端章节。
- 已根据业务需要创建具有相应权限的组件业务用户。“机机”用户需要下载keytab文件,“人机”用户第一次登录时需修改密码。
使用HIndexImportTsv批量生成HBase本地二级索引数据
- 以客户端安装用户登录安装了客户端的节点。
- 执行以下命令配置环境变量并认证用户:
cd 客户端安装目录
配置环境变量:
source bigdata_env
认证用户,集群未启用Kerberos认证(普通模式)请跳过该操作:
kinit 组件业务用户
- 将数据导入到HDFS中。
hdfs dfs -mkdir <inputdir>
将数据文件上传至HDFS中:
hdfs dfs -put <local_data_file> <inputdir>
例如定义数据文件“data.txt”,内容如下:
12005000201,Zhang San,Male,19,City a, Province a 12005000202,Li Wanting,Female,23,City b, Province b 12005000203,Wang Ming,Male,26,City c, Province c 12005000204,Li Gang,Male,18,City d, Province d 12005000205,Zhao Enru,Female,21,City e, Province e 12005000206,Chen Long,Male,32,City f, Province f 12005000207,Zhou Wei,Female,29,City g, Province g 12005000208,Yang Yiwen,Female,30,City h, Province h 12005000209,Xu Bing,Male,26,City i, Province i 12005000210,Xiao Kai,Male,25,City j, Province j
执行以下命令上传“data.txt”文件:
创建“datadirImport”目录:
hdfs dfs -mkdir /datadirImport
上传“data.txt”文件至HDFS的“datadirImport”目录中:
hdfs dfs -put data.txt /datadirImport
- 执行以下命令创建表bulkTable:
- 登录HBase客户端:
hbase shell
- 创建表bulkTable:
create 'bulkTable', {NAME => 'info',COMPRESSION => 'SNAPPY', DATA_BLOCK_ENCODING => 'FAST_DIFF'},{NAME=>'address'} - 命令执行完成后,再执行以下命令退出hbase shell:
!quit
- 登录HBase客户端:
- 执行如下命令,生成HFile文件(StoreFiles):
hbase org.apache.hadoop.hbase.hindex.mapreduce.HIndexImportTsv -Dimporttsv.separator=<separator> -Dimporttsv.bulk.output=</path/for/output> -Dindexspecs.to.add=<indexspecs> -Dimporttsv.columns=<columns> tableName <inputdir>
表1 参数介绍 参数
参数说明
-Dimport.separator
该参数用于指定数据文件中字段间的分隔符。例如-Dimporttsv.separator=','表示字段间以逗号分隔。
-Dimport.bulk.output
该参数用于指定HFile文件的输出路径,需指定一个不存在的HDFS路径。生成的HFile文件将保存在该路径下。
-Dindexspecs.to.add
表示索引名与列的映射,例如-Dindexspecs.to.add='index_bulk=>info:[age->String]'。
其构成如下所示:
indexNameN=>familyN :[columnQualifierN-> columnQualifierDataType], [columnQualifierM-> columnQualifierDataType];familyM: [columnQualifierO-> columnQualifierDataType]# indexNameN=> familyM: [columnQualifierO-> columnQualifierDataType]
其中:
- 列限定符用逗号(,)分隔,例如:
- 列族用分号(;)分隔,例如:
- 多个索引用#号分隔,例如:
index1 => f1:[c1-> String], [c2-> String]; f2:[c3-> Long]#index2 => f2:[c3-> Long]
- 列限定的数据类型
- 数据类型也可以用小写传递。
-Dimporttsv.columns
该参数用于指定导入数据在表中的列映射关系。格式为:HBASE_ROW_KEY,列族:列限定符,列族:列限定符...。
例如-Dimporttsv.columns=HBASE_ROW_KEY,info:name,info:gender,info:age,address:city,address:province表示第一列作为RowKey,后续列分别映射到info和address列族。
tableName
该参数用于指定要操作的HBase表名称。
<inputdir>
该参数用于指定HDFS中待导入数据的目录路径。
例如执行以下命令:
hbase org.apache.hadoop.hbase.hindex.mapreduce.HIndexImportTsv -Dimporttsv.separator=',' -Dimporttsv.bulk.output=/dataOutput -Dindexspecs.to.add='index_bulk=>info:[age->String]' -Dimporttsv.columns=HBASE_ROW_KEY,info:name,info:gender,info:age,address:city,address:province bulkTable /datadirImport/data.txt
命令执行后,输出以下内容:
2018-05-08 21:29:16,059 INFO [main] mapreduce.HFileOutputFormat2: Incremental table bulkTable output configured. 2018-05-08 21:29:16,069 INFO [main] client.ConnectionManager$HConnectionImplementation: Closing master protocol: MasterService 2018-05-08 21:29:16,069 INFO [main] client.ConnectionManager$HConnectionImplementation: Closing zookeeper sessionid=0x80007c2cb4fd5b4d 2018-05-08 21:29:16,072 INFO [main] zookeeper.ZooKeeper: Session: 0x80007c2cb4fd5b4d closed 2018-05-08 21:29:16,072 INFO [main-EventThread] zookeeper.ClientCnxn: EventThread shut down for session: 0x80007c2cb4fd5b4d 2018-05-08 21:29:16,379 INFO [main] client.ConfiguredRMFailoverProxyProvider: Failing over to 147 2018-05-08 21:29:17,328 INFO [main] input.FileInputFormat: Total input files to process : 1 2018-05-08 21:29:17,413 INFO [main] mapreduce.JobSubmitter: number of splits:1 2018-05-08 21:29:17,430 INFO [main] Configuration.deprecation: io.bytes.per.checksum is deprecated. Instead, use dfs.bytes-per-checksum 2018-05-08 21:29:17,687 INFO [main] mapreduce.JobSubmitter: Submitting tokens for job: job_1525338489458_0002 2018-05-08 21:29:18,100 INFO [main] impl.YarnClientImpl: Submitted application application_1525338489458_0002 2018-05-08 21:29:18,136 INFO [main] mapreduce.Job: The url to track the job: http://shap000000407:8088/proxy/application_1525338489458_0002/ 2018-05-08 21:29:18,136 INFO [main] mapreduce.Job: Running job: job_1525338489458_0002 2018-05-08 21:29:28,248 INFO [main] mapreduce.Job: Job job_1525338489458_0002 running in uber mode : false 2018-05-08 21:29:28,249 INFO [main] mapreduce.Job: map 0% reduce 0% 2018-05-08 21:29:38,344 INFO [main] mapreduce.Job: map 100% reduce 0% 2018-05-08 21:29:51,421 INFO [main] mapreduce.Job: map 100% reduce 100% 2018-05-08 21:29:51,428 INFO [main] mapreduce.Job: Job job_1525338489458_0002 completed successfully 2018-05-08 21:29:51,523 INFO [main] mapreduce.Job: Counters: 50
- 执行如下命令将生成的HFile导入HBase中:
hbase org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles </path/for/output> <tablename>
例如执行以下命令:
hbase org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles /dataOutput bulkTable
命令执行后,输出以下内容:
2018-05-08 21:30:01,398 WARN [main] mapreduce.LoadIncrementalHFiles: Skipping non-directory hdfs://hacluster/dataOutput/_SUCCESS 2018-05-08 21:30:02,006 INFO [LoadIncrementalHFiles-0] hfile.CacheConfig: Created cacheConfig: CacheConfig:disabled 2018-05-08 21:30:02,006 INFO [LoadIncrementalHFiles-2] hfile.CacheConfig: Created cacheConfig: CacheConfig:disabled 2018-05-08 21:30:02,006 INFO [LoadIncrementalHFiles-1] hfile.CacheConfig: Created cacheConfig: CacheConfig:disabled 2018-05-08 21:30:02,085 INFO [LoadIncrementalHFiles-2] compress.CodecPool: Got brand-new decompressor [.snappy] 2018-05-08 21:30:02,120 INFO [LoadIncrementalHFiles-0] mapreduce.LoadIncrementalHFiles: Trying to load hfile=hdfs://hacluster/dataOutput/address/042426c252f74e859858c7877b95e510 first=12005000201 last=12005000210 2018-05-08 21:30:02,120 INFO [LoadIncrementalHFiles-2] mapreduce.LoadIncrementalHFiles: Trying to load hfile=hdfs://hacluster/dataOutput/info/f3995920ae0247a88182f637aa031c49 first=12005000201 last=12005000210 2018-05-08 21:30:02,128 INFO [LoadIncrementalHFiles-1] mapreduce.LoadIncrementalHFiles: Trying to load hfile=hdfs://hacluster/dataOutput/d/c53b252248af42779f29442ab84f86b8 first=\x00index_bulk\x00\x00\x00\x00\x00\x00\x00\x0018\x00\x0012005000204 last=\x00index_bulk\x00\x00\x00\x00\x00\x00\x00\x0032\x00\x0012005000206 2018-05-08 21:30:02,231 INFO [main] client.ConnectionManager$HConnectionImplementation: Closing master protocol: MasterService 2018-05-08 21:30:02,231 INFO [main] client.ConnectionManager$HConnectionImplementation: Closing zookeeper sessionid=0x81007c2cf0f55cc5 2018-05-08 21:30:02,235 INFO [main] zookeeper.ZooKeeper: Session: 0x81007c2cf0f55cc5 closed 2018-05-08 21:30:02,235 INFO [main-EventThread] zookeeper.ClientCnxn: EventThread shut down for session: 0x81007c2cf0f55cc5
验证操作:
数据加载完成后,可通过以下方式验证数据和索引是否成功导入:
常见问题
- HIndexImportTsv任务执行失败
HIndexImportTsv任务执行失败的常见原因包括:HDFS输入路径不存在或无读取权限、输出路径已存在(需指定不存在的路径)、表不存在且未指定建表参数、数据文件格式与列映射定义不匹配、Yarn集群资源不足导致MapReduce任务无法提交等。
- LoadIncrementalHFiles加载HFile失败
LoadIncrementalHFiles加载HFile失败的常见原因包括:HFile输出路径不存在或为空、HFile格式不正确、表结构发生变化导致HFile与表不兼容、Region正在分裂或合并导致加载冲突、用户没有表的写入权限等。
相关文档
- 了解HBase本地二级索引的原理和特性,请参考HBase本地二级索引介绍。
- 了解如何使用TableIndexer工具生成HBase本地二级索引,请参考使用TableIndexer工具生成HBase本地二级索引。
- 了解HBase数据操作,请参考HBase数据操作。