一、安装Sqoop
环境准备
Sqoop是一款基于Hadoop系统的数据转移工具,因此在安装Sqoop之前需要先安装好Hadoop。
本文使用的各软件版本如下:
操作系统:ubuntu-14.04.1-desktop-amd64
Hadoop版本:hadoop-2.7.1
MySQL版本:5.5.54
MySQL驱动:mysql-connector-java-5.1.20-bin.jar
Sqoop版本:sqoop-1.4.6.bin__hadoop-2.0.4-alpha.tar.gz
安装步骤
1. 下载Sqoop
从Apache官网下载Sqoop的最新稳定版本,下载网址为:https://sqoop.apache.org
本文例子使用的是sqoop-1.4.6版本。
2. 安装Sqoop
1)将下载的Sqoop安装文件上传到Ubuntu系统合适目录(例如usr/local),然后进行解压。解压命令如下:
tar -zxvf sqoop-1.4.6.bin__hadoop-2.0.4-alpha.tar.gz
2)将解压后的文件夹sqoop-1.4.6.bin__hadoop-2.0.4-alpha进行重命名为sqoop-1.4.6,代码如下:
mv sqoop-1.4.6.bin__hadoop-2.0.4-alpha sqoop-1.4.6
3)为了以后的操作方便,对Sqoop的环境变量进行配置,在/etc/profile文件中加入以下内容:
export SQOOP_HOME=/usr/local/sqoop-1.4.6
export PATH=$SQOOP_HOME/bin:$PATH
加入后执行source /etc/profile命令对环境变量文件进行刷新。
4)拷贝${SQOOP_HOME}/conf/sqoop-env-template.sh 到${SQOOP_HOME}/conf/sqoop-env.sh,然后修改sqoop-env.sh,加入HADOOP_COMMON_HOME和HADOOP_MAPRED_HOME,指定Hadoop安装目录,如下:
export HADOOP_COMMON_HOME=/usr/local/hadoop-2.7.1
export HADOOP_MAPRED_HOME=/usr/local/hadoop-2.7.1
5)测试是否安装成功,执行列出mysql中的数据库命令:
sqoop list-databases --connect jdbc:mysql://192.168.1.69:3306/test --username root --password 123456
注意:
--connect参数为MySQL数据库的连接地址。
--username参数为MySQL数据库的用户名。
--password参数为MySQL数据库的密码。
本例执行的操作结果如下:
输出结果为:
information_schema
im
mysql
oa
performance_schema
score
test
如果能成功列出MySQL中的数据库列表,说明安装成功。
二、使用Sqoop将MySQL中的表数据导入到HDFS
案例描述
将MySQL 中数据库test中的表user_info导入到HDFS中,表user_info中有两条数据,截图如下:
表user_info
操作步骤
- 启动Hadoop
start-all.sh
- 执行导入命令
sqoop import \
--connect jdbc:mysql://192.168.1.69/test?characterEncoding=UTF-8 \
--username root --password 123456 \
--table user_info \
--columns userId,userName,password,trueName,addedTime \
--target-dir /sqoop/mysql
从命令中可以看出,导入的HDFS目录为/sqoop/mysql。如果HDFS不存在此目录,则会新建该目录。
执行过程如下图:
image.png
图中出现的警告信息我们先忽略不计。从图中可以看出,导入过程只使用了map任务,没有使用reduce。其中输出了一句SQL语句:SELECT MIN(userId
), MAX(userId
) FROM user_info
,至于为什么会这样输出,将在后续讲解。
- 查看导入结果
执行下面命令,查看/sqoop/mysql目录下生成的文件:
hadoop fs -ls /sqoop/mysql
显示结果如下:
root@master:~# hadoop fs -ls /sqoop/mysql
Found 3 items
-rw-r--r-- 2 root supergroup 0 2017-11-16 17:23 /sqoop/mysql/_SUCCESS
-rw-r--r-- 2 root supergroup 33 2017-11-16 17:23 /sqoop/mysql/part-m-00000
-rw-r--r-- 2 root supergroup 34 2017-11-16 17:23 /sqoop/mysql/part-m-00001
说明在HDFS文件系统中生成了三个文件_SUCCESS、part-m-00000、part-m-00001,而我们的数据正是存在后两个文件中。分别查看生成的后两个文件中的内容,可以看到MySQL中的每一行数据生成了一个文件:
查看每一个文件中的数据
执行下面命令,查看/sqoop/mysql/文件夹下所有文件的内容:
hadoop fs -cat /sqoop/mysql/*
显示结果如下:
image.png
三、使用Sqoop将HDFS中的数据导出到MySQL表
-
在MySQL数据库test中新建表user_info_2,字段如下:
表user_info_2 - 将HDFS文件系统/sqoop/mysql/part-m-00000文件中的内容导出到表user_info_2中,导出命令如下:
sqoop export \
--connect jdbc:mysql://192.168.1.69:3306/test?characterEncoding=UTF-8 \
--username root \
--password 123456 \
--table user_info_2 \
--export-dir /sqoop/mysql/part-m-00000
导出成功后,刷新表user_info_2,查看其中的数据:
表user_info_2
可以看到,多了一条数据。当然,也可以将HDFS中/sqoop/mysql目录下的所有文件一起导出到表user_info_2中,只需将上述导出命令中的/sqoop/mysql/part-m-00000替换为/sqoop/mysql/*即可。
四、使用Sqoop将Mysql表数据导入到HBase
Mysql中的表user_info有两条数据,如下:
表user_info
1.启动hbase
start-hbase.sh
2.在hbase中新建表user_info,列族baseinfo
create 'user_info','baseinfo'
3.执行导入命令:
sqoop import \
--connect jdbc:mysql://192.168.1.69/test?characterEncoding=UTF-8 \
--username root --password 123456 \
--query "SELECT * FROM user_info WHERE 1=1 AND \$CONDITIONS" \
--hbase-table user_info \
--column-family baseinfo \
--hbase-row-key userId \
--split-by addedTime \
--m 2
反斜杠后面紧跟回车,表示下一行是当前行的续行。
参数说明:
--hbase-table 指定要导入的HBase中的表名。
--column-family 指定要导入的HBase表的列族。
--hbase-row-key 指定mysql中的某一列作为HBase表中的rowkey。
--split-by 指定mysql中的某一列作为分区导入。默认是主键。
--m 指定复制过程使用的map作业的数量。
sqoop是如何根据--split-by进行分区的?
假设有一张表test,sqoop命令中--split-by id --m 10。首先,sqoop会去查表的元数据,sqoop会向关系型数据库比如mysql发送一个命令:select max(id),min(id) from test。然后会把max、min之间的区间平均分为10分,最后10个并行的map去找数据库,导数据就正式开始了。
- 查看导入结果
进入hbase shell,扫描user_info表中的数据,命令及执行效果如下:
hbase(main):001:0> scan 'user_info'
ROW COLUMN+CELL
1 column=baseinfo:addedTime, timestamp=1510887550010, value=2017-06-21
1 column=baseinfo:password, timestamp=1510887550010, value=123456
1 column=baseinfo:trueName, timestamp=1510887550010, value=zhangsan
1 column=baseinfo:userName, timestamp=1510887550010, value=hello
2 column=baseinfo:addedTime, timestamp=1510887550110, value=2017-06-10
2 column=baseinfo:password, timestamp=1510887550110, value=123456
2 column=baseinfo:trueName, timestamp=1510887550110, value=lisi
2 column=baseinfo:userName, timestamp=1510887550110, value=hello2
2 row(s) in 0.6870 seconds
可以看到,两条数据已经成功导入。
如果修改user_info中的数据,重新导入,则会更新替换hbase中相同rowkey对应行的数据。
注意的问题:如果mysql表中存在中文,导入到hbase表中的结果如下:
MySQL表:
导入hbase后的结果:
image.png
中文变成了十六进制字符,我们把其中一个trueName值\xE5\xBC\xA0\xE4\xB8\x89转成中文,结果如下:
image.png
说明中文确实是转成了十六进制,我们从HBase中取数据时,将十六进制转成中文即可。
上方操作是提前在HBase中创建了相应的表,当然也可以提前不创建hbase表,在导入命令中指定创建表参数,如果表不存在则会创建表,如下:
sqoop import \
--connect jdbc:mysql://192.168.1.69/test \
--username root --password 123456 \
--query "SELECT * FROM user_info WHERE 1=1 AND \$CONDITIONS" \
--hbase-table user_info \
--column-family baseinfo \
--hbase-create-table \
--hbase-row-key userId \
--split-by addedTime \
--m 2
但是这种方式经过测试,出现bug,创建表不成功,原因是hbase中缺少Sqoop需要的API类。说明当前Sqoop版本与HBase版本不兼容。HBase我使用的是1.2.4版本。
如果大家有其它好的意见,欢迎在下方留言。
网友评论