本文是为了记录工作中用到的技术方案,为了把hive中的表从集群1迁移到集群2映射成hbase表的。
1.方案一
查询hive的表先在本地生成制表符文件(csv,tsv),上传到HDFS路径下,远程复制到集群2的HDFS路径下去,然后使用hbase自带的映射工具-importtsv,bulkload等映射成hbase表。
说明:前提是在一个集群中这样操纵比较方便,但是目前情况是两个集群进行操作,中间设计到ssh登录到集群2的远程机器(因为这里有hbase的操作环境)。这样的话太麻烦。
但是上面的也是要远程连接到集群2的某个机器的,实施起来比较麻烦。本来想是在一个shell脚本中完成这些操作的,因为ssh远程连接的话,风险1是要输入目标集群的机器的密码,风险2就是当ssh方式登录完以后直接在shell脚本中执行hbase命令是无法执行的,后来经过各种尝试,写在expect文件(也就是我要执行的ssh命令)里面写入了在目标机器要执行的命令,也算完成了。类似于下面的expect文件的格式。我这里是把hbase的命令放在了shell脚本来执行的。
远程复制csv完成之后 ,我们来理一下shell的部分
shell脚本的内容包含两部分:
1部分是生成csv文件并远程复制到hbase的集群的shell脚本
2部分是下面的在hbase机器上执行的hbase命令。
其中是把.d.sh文件和。password文件上传到调度工具可以访问到的机器目录下面就可以。
文件前面加.也就是隐藏文件。
1)expect文件 vi .d.sh
其中密码是通过执行.d.sh的时候传入的,记得chmod .d.sh。
2) file.sh
#/bin/bash
tablename_hbase=$1
tablename=$2
hbase org.apache.hadoop.hbase.mapreduce.ImportTsv -Dimporttsv.columns='HBASE_ROW_KEY,info:id,info:type,info:unit,info:qty' -Dimporttsv.bulk.output=/user/hadoop/profile/output_${tablename_hbase} default:${tablename_hbase} hdfs://ip:8020/user/hadoop/profile/${tablename}.csv
HADOOP_CLASSPATH=`hbase classpath` hadoop jar /opt/cloudera/parcels/CDH-5.10.0-1.cdh5.10.0.p0.41/lib/hbase/hbase-server-1.2.0-cdh5.10.0.jar completebulkload /user/hadoop/profile/output_${tablename_hbase} default:${tablename_hbase}
但是这样的话是太复杂了,而且传的参数hba’se的表和hive表也会变化,这样意味着shell脚本1执行的时候调用的脚本2得进行修改。
因为做映射的时候每个hbase表对应的列族和列的名字是不一样的。
所以方案1不太理想。
因为hive自己本身有生成到HDFS路径的命令,insert overwrite directory hdfs路径 + hql 语句。
1.下面图的前3步
vi hive2hbase.sh
#/bin/bash
# $1是hdfs路径;$2hive库名;$3hive表名;$4分区名字;$5hbase环境的集群2对应的HDFS路径;
echo "insert overwrite DIRECTORY '$1' ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' SELECT * FROM $2.$3 where dt='$4'"
hive -e "insert overwrite DIRECTORY '$1' ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' SELECT * FROM $2.$3 where dt='$4'"
#远程复制,首先确保远程HDFS路径是空白的,因为这个在重跑数据的时候不会覆盖。
hadoop distcp -D ipc.client.fallback-to-simple-auth-allowed=true -m 30 $1 $5
执行过程
sh hive2hbase.sh 集群1的hdfs_path 库名 表名 20181005 集群2的hdfs_path。
一般hdfs路径可以和表名相关,这样也知道是从哪个hive表导出的数据。
hdfs://ns1/user/hadoop/profile/表名
但是要重跑数据,删除集群2的HDFS文件的时候要远程连接到集群2的某个机器的,实施起来比较麻烦,
不行的话到时候就手动删除,或者是在hbase的文件目录下面新建一个子目录分区时间。
后面的java代码改成了在离线集群下面的机器命令行上执行下面的命令:
对于Bulk CSV Data Loading的方法,要求对于Phoenix 4.0+的版本,指定 HADOOP_CLASSPATH=$(hbase mapredcp)
#/bin/bash
export HADOOP_CLASSPATH="/opt/cloudera/parcels/CLABS_PHOENIX/lib/phoenix/lib/hbase-protocol-1.2.0-cdh5.7.0.jar";
#如果下面的命令执行失败的时候先执行上面的命令。
hadoop jar /opt/cloudera/parcels/CLABS_PHOENIX/lib/phoenix/phoenix-4.7.0-clabs-phoenix1.3.0-client.jar org.apache.phoenix.mapreduce.CsvBulkLoadTool -Dfs.permissions.umask-mode=000 -t ‘hbase表名大写’ -i 离线集群的hdfs文件的HDFS路径 -z ZK对应的master节点的ip:2181
1.phoenix建表语句:
create table table2
(st_name VARCHAR NOT NULL,
st_value VARCHAR,
CONSTRAINT PK PRIMARY KEY(st_name)
) COMPRESSION=‘SNAPPY’, SALT_BUCKETS=10;
2.在BDI调度能访问的机器上面的某个目录下创建shell脚本
vi hive2hbase.sh
#/bin/bash
#读取hive表文件到HDFS目录下
#hdfs_path=$1 hdfs://ns1/user/hadoop/profile/table
#database = $2 adm_profile
#tablename= $3 dt= $4
#hdfs_hbase=$5 hdfs://ip:8020/user/hadoop/profile/dt
#tablename_hbase=$6 hbasetable大写的
echo "insert overwrite DIRECTORY '$1' ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' SELECT * FROM $2.$3 where dt='$4'"
hive -e "insert overwrite DIRECTORY '$1' ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' SELECT * FROM $2.$3 where dt='$4'"
#远程复制
hadoop distcp -D ipc.client.fallback-to-simple-auth-allowed=true -m 30 $1 $5
#这里对.password和.d.sh两个文件进行了隐藏。
var=`cat /mnt/bigdata-bdi/bigdata/data_warehouse/.password`
#echo "$var"
/mnt/bigdata-bdi/bigdata/data_warehouse/.d.sh $var $6 $5
#HBASE集群执行此命令
#hadoop jar /opt/cloudera/parcels/CLABS_PHOENIX/lib/phoenix/phoenix-4.7.0-clabs-phoenix1.3.0-client.jar org.apache.phoenix.mapreduce.CsvBulkLoadTool -Dfs.permissions.umask-mode=000 -t '大写的HBASE表名' -i 离线集群的hdfs文件的HDFS路径 -z ZK对应的master节点的ip:2181
#如果上面的命令执行失败就先执行这个
#export HADOOP_CLASSPATH="/opt/cloudera/parcels/CLABS_PHOENIX/lib/phoenix/lib/hbase-protocol-1.2.0-cdh5.7.0.jar";
vi .d.sh
#!/usr/bin/expect
set timeout 30000
set password [lindex $argv 0]
set hbase_table [lindex $argv 1]
set hbase_path [lindex $argv 2]
spawn ssh hadoop@远程连接的目标机器ip "cd /home/hadoop/tmp ; sh file2table.sh $hbase_table $hbase_path"
expect "*password*"
send "$password\r"
#send "sudo -s\r"
#send "cd \r"
interact
chmod +x .d.sh 记得给这个文件加执行权限
vi .password
远程连接的目标机器ip的Hadoop用户对应的密码
3.执行流程:
sh hive2hbase.sh hdfs_path database tablename dt hdfs_hbase hbase_table
通过方案二的改良版就创建了phoenix表,然后查询hbase表的话就可以通过sql的i形式查询phoenix表进而查询hbase了,此外还可以使用联合索引的方式创建对应的INDEX表,就可以多维度进行查询了。
4.INDEX联合索引创建以及查询:
链接:https://blog.csdn.net/u011491148/article/details/45749807