Phoenix 官方提供了相应的导入和导出的方案,分别位于:
导入: https://phoenix.apache.org/bu...
导入、导出: https://phoenix.apache.org/pi...
导出需要依赖 Apache Pig
相应进行实现。我们先来聊聊如何导出吧。
环境:HDP 3.0.0、HBase 2.0.0、Phoenix 5.0.0、Pig 0.16.0
Phoenix 官方提供的 Pig 方案,看似很简单,其实还是有很多需要注意的地方,比较官方给的都是最简单的示例,而实际应用场景的时候,会碰到很多意想不到的问题。我在本文就讲讲我的实现方法和遇到的坑吧。
以下操作需要先安装 Pig 环境。
test.pig
REGISTER /usr/hdp/3.0.0.0-1634/hbase/lib/*.jar; REGISTER lib/*.jar; rows = load 'hbase://table/DOP_VISIT_INFO_V2' USING org.apache.phoenix.pig.PhoenixHBaseLoader('dev-dmp3.fengdai.org,dev-dmp4.fengdai.org,dev-dmp5.fengdai.org');
hbase://table/DOP_VISIT_INFO_V2
:是指需要备份的表,如果是全表就用 hbase://table
,后面跟表名,这里就是 DOP_VISIT_INFO_V2
查询的结果导出则用 hbase://query
,后面跟查询语句。 PhoenixHBaseLoader 参数
:ZooKeeper 地址。 执行语句:
pig -x mapreduce test.pig
相应的导出的数据是存储在 HDFS 上,需要留意一下脚本执行完以后相应的日志中会有体现。
REGISTER /usr/hdp/3.0.0.0-1634/hbase/lib/*.jar; REGISTER lib/*.jar; rows = load 'hbase://table/DOP_VISIT_INFO_V2' USING org.apache.phoenix.pig.PhoenixHBaseLoader('dev-dmp3.fengdai.org,dev-dmp4.fengdai.org,dev-dmp5.fengdai.org'); STORE rows INTO 'dop_visit_info_v2.csv' USING PigStorage(',');
STORE rows INTO 'dop_visit_info_v2.csv' USING PigStorage(',')
:导出到 HDFS 的文件路径和数据存储格式,这里就是存放 dop_visit_info_v2.csv
目录下,这里千万注意,这是一个文件夹,而不是一个 csv
文件,起初,我也很单纯的以为,Too Young,使用逗号进行分隔。
REGISTER /usr/hdp/3.0.0.0-1634/hbase/lib/*.jar; REGISTER lib/*.jar; rows = load 'hbase://query/select * DOP_VISIT_INFO_V2 where age >18' USING org.apache.phoenix.pig.PhoenixHBaseLoader('dev-dmp3.fengdai.org,dev-dmp4.fengdai.org,dev-dmp5.fengdai.org');
注意:使用query语句指定的导出方式存在很大的限制,比如说不能指定 GROUP BY , LIMIT , ORDER BY , DISTINCT
;同时也无法指定使用聚合函数,如 count,sum
等。
数据存储在 HDFS 下哦。
hdfs dfs -cat '/dop_visit_info_v2.csv/part-m-00000'
Phoenix 支持使用 Pig StoreFunc 实现 bulk upload
数据导入。
REGISTER /usr/hdp/3.0.0.0-1634/hbase/lib/*.jar; REGISTER lib/*.jar; A = load 'gejx.csv' USING PigStorage(',') as (ID:chararray, DOP_VISIT_VISITID:chararray); STORE A into 'hbase://GEJX_TEST' using org.apache.phoenix.pig.PhoenixHBaseStorage('dev-dmp3.fengdai.org,dev-dmp4.fengdai.org,dev-dmp5.fengdai.org','-batchSize 100');
gejx.csv hbase://GEJX_TEST -batchSize 100 ID:chararray, DOP_VISIT_VISITID:chararray USING PigStorage(',')
注意:表需要提前创建哦,否则,会报表不存在。
Pig 数据类型默认是 chararray,常用数据类型为:int、long、float、double、chararray、bytearray、map、tuple、bag。
详细查看 pig 数据类型 。
如果 Phoenix 表中存在 null 值,通过 Pig 方式导入导出数据会存在 null 变成了空字符串。
在使用 https://phoenix.apache.org/bu... 中 MR 方式时,由于 HDP 环境开启了 Kerberos 模式,一直遇到了认证的问题,后来发现支持 -D
的语法,不过这里需要注意的是一定要放在 hadoop jar 参数命令之前,否则会报没有这个命令的错误。
hadoop jar /usr/hdp/3.0.0.0-1634/phoenix/phoenix-5.0.0.3.0.0.0-1634-client.jar org.apache.phoenix.mapreduce.CsvBulkLoadTool -Dhbase.master.kerberos.principal=hbase/_HOST@DEV.ORG -Dhbase.regionserver.kerberos.principal=hbase/_HOST@DEV.ORG -Dhadoop.security.authentication=kerberos -Dhbase.security.authentication=kerberos -Dphoenix.schema.isNamespaceMappingEnabled=true -Dphoenix.schema.mapSystemTablesToNamespace=false -Dphoenix.queryserver.withRemoteUserExtractor=true --table GEJX_TEST --input /user/dmpadmin/gejx.csv -z dev-dmp3.fengdai.org,dev-dmp4.fengdai.org,dev-dmp5.fengdai.org:/hbase-secure
phoenix-5.0.0.3.0.0.0-1634-client.jar
该包是存放在 Phoenix 安装目录下的,并不是 lib 目录。
以上的方式导入和导出是相互割裂的,而有一种场景在生产上也碰到的很多,就是表与表之间的数据同步,比如,现在有两张表 A 表和 B 表,表部分字段一样,字段名称不一样,现在需要将 A 表中的数据同步到 B 表,我们也可以通过 Pig 方式实现。
REGISTER /usr/hdp/3.0.0.0-1634/hbase/lib/*.jar; REGISTER lib/*.jar; A = load 'hbase://query/select * from GEJX' USING org.apache.phoenix.pig.PhoenixHBaseLoader('dev-dmp3.fengdai.org,dev-dmp4.fengdai.org,dev-dmp5.fengdai.org'); STORE A into 'hbase://GEJX_TEST' using org.apache.phoenix.pig.PhoenixHBaseStorage('dev-dmp3.fengdai.org,dev-dmp4.fengdai.org,dev-dmp5.fengdai.org','-batchSize 100');
将导入和导出放在一起进行操作,batchSize 可以根据实际情况进行相应的调整。
Zookeeper 端口配置
zk1:2181,zk2:2181,zk3:2181
Kerberos 认证
开启 Keberos 模块的场景下,需要提前在 Pig 所在服务器下进行 kinit 操作
org.apache.pig.PigServer - exception during parsing: Error during parsing. null Failed to parse: null
一般是语法错误导致的。
ERROR org.apache.pig.tools.grunt.GruntParser - ERROR 0: java.io.IOException: java.lang.RuntimeException: java.lang.Integer cannot be coerced to TINYINT
这个问题就无法解决了,目标表的不能使用 TINYINT 类型。