大家好,我是一哥,昨天看到了过往记忆大佬发了一篇文章,才发现Sqoop这个项目最近不咋好,心里很不是滋味,这个帮助过很多开发者的项目,竟然从Apache顶级项目中“下架”了,今天还是想给大家分享介绍一些这个很棒的项目,致敬!
01
Sqoop介绍
Sqoop is a tool designed to transfer data between Hadoop and relational databases or mainframes. You can use Sqoop to import data from a relational database management system (RDBMS) such as MySQL or Oracle or a mainframe into the Hadoop Distributed File System (HDFS), transform the data in Hadoop MapReduce, and then export the data back into an RDBMS.
Sqoop是一种用于在Hadoop和关系数据库或大型机之间传输数据的工具。你可以使用Sqoop从一个关系数据库管理系统(RDBMS)中导入数据,比如MySQL或Oracle,或者一个大型机到Hadoop分布式文件系统(HDFS),在Hadoop MapReduce中转换数据,然后将数据导出到RDBMS中。
其实我们不使用Sqoop也可以完成MySQL和HDFS的数据传递,采用Flume监控MySQL,能读到数据,那么也就能把数据写到HDFS上。
02
Sqoop原理
其实Sqoop做的就是把导入导出命令翻译成MapReduce程序来实现,该MapReduce程序主要是对InputFormat和OutputFormat进行定制。和Flume一样,没有什么bin/start.sh,不用启动任何进程,一个任务就对应一个MapReduce。
03Sqoop的安装和配置
目前Sqoop有两个版本,Sqoop1(1.4.x)和Sqoop2(1.99.x),Sqoop1最新版本是1.4.7,Sqoop2最新版本是1.99.7(注意:1.99.7和1.4.7不兼容,且功能不完整),另外Sqoop1.4.7和CentOS6.8配合有问题,要改很多地方,所以使用1.4.6。
1、去官网(http://archive.apache.org/dist/sqoop/)下载压缩包:
2、解压、重命名
代码语言:javascript复制tar -zxvf sqoop-1.4.6.bin__hadoop-2.0.4-alpha.tar.gz -C /opt/module/
cd /opt/module/
cp -r sqoop-1.4.6.bin__hadoop-2.0.4-alpha/ sqoop-1.4.6
注意:Sqoop只是一个工具,所以不需要分发到其他设备上
3、配置
代码语言:javascript复制cp conf/sqoop-env-template.sh conf/sqoop-env.sh
vim conf/sqoop-env.sh
#Set path to where bin/hadoop is available
export HADOOP_COMMON_HOME=/opt/module/hadoop-2.7.2
#Set path to where hadoop-*-core.jar is available
export HADOOP_MAPRED_HOME=/opt/module/hadoop-2.7.2
#set the path to where bin/hbase is available
export HBASE_HOME=/opt/module/hbase-1.3.2.1
#Set the path to where bin/hive is available
export HIVE_HOME=/opt/module/hive-1.2.2
#Set the path for where zookeper config dir is
export ZOOCFGDIR=/opt/module/zookeeper-3.4.10
因为Sqoop要从Mysql导入数据,又会把数据导出到Mysql,都需要Mysql Java驱动jar,所以需要把MySQL的驱动jar包copy到Sqoop的./lib目录下。
代码语言:javascript复制cp /opt/soft/mysql-libs/mysql-connector-java-5.1.27/mysql-connector-java-5.1.27-bin.jar ./lib/
验证Sqoop是否配置正确:
代码语言:javascript复制bin/sqoop help
我们之前并没有在sqoop.env.sh中配置MySQL的相关内容,是因为我们在执行命令的时候,要主动地在命令当中去连接我们的MySQL。
测试Sqoop能否成功连接数据库:
代码语言:javascript复制bin/sqoop list-databases --connect jdbc:mysql://hadoop102:3306/ --username root --password 123456
04
Sqoop简单使用案例
MySQL --> HDFS
全表导入:
代码语言:javascript复制bin/sqoop import
# ====== MySQL的配置 ======
--connect jdbc:mysql://hadoop102:3306/company
--username root
--password 123456
# 要导入的表名是staff,表示staff表全表导入!
--table staff
# ====== HDFS的配置 ======
# 要导入到HDFS的哪个目录
--target-dir /user/company
# 因为Sqoop原理就是跑MR,MR不允许输出目录存在,这个参数的意思就是target-dir目录存在则删除
# 但是现在仅是为了学习使用这个参数,实际到公司中慎用,避免删除数据!
--delete-target-dir
# maptask并不像以前MR读文件会切片,得根据实际表的数据量大小自己估计下maptask
--num-mappers 1
# 字段分割符是t
--fields-terminated-by "t"
查询导入:
代码语言:javascript复制bin/sqoop import
# ====== MySQL的配置 ======
--connect jdbc:mysql://hadoop102:3306/company
--username root
--password 123456
# 必须在where字句中加上$CONDITIONS保证导入的数据顺序
--query 'select name,sex from staff where id <=2 and $CONDITIONS'
# ====== HDFS的配置 ======
--target-dir /user/company
--delete-target-dir
--num-mappers 1
--fields-terminated-by "t"
Sqoop把数据库的数据导入到HDFS上,应该保证数据的顺序和查询的结果集一致才行!但是实际开发中,数据量很大,我们不可能只分配一个mapper工作,所以我们得加上$CONDITIONS保证多个maptask写入到HDFS上的文件数据的顺序和原表查询的结果一致!
If you want to import the results of a query in parallel, then each map task will need to execute a copy of the query, with results partitioned by bounding conditions inferred by Sqoop. Your query must include the token $CONDITIONS which each Sqoop process will replace with a unique condition expression. You must also select a splitting column with --split-by.
导入指定列:
代码语言:javascript复制bin/sqoop import
# ====== MySQL的配置 ======
--connect jdbc:mysql://hadoop102:3306/company
--username root
--password 123456
--table staff
# 指定列,如果是多个列用,分隔,分隔时不要加空格,否则会抛异常
--columns id,sex
# ====== HDFS的配置 ======
--target-dir /user/company
--delete-target-dir
--num-mappers 1
--fields-terminated-by "t"
查询条件导入:
代码语言:javascript复制bin/sqoop import
# ====== MySQL的配置 ======
--connect jdbc:mysql://hadoop102:3306/company
--username root
--password aaa
--table staff
# 指定查询条件
--where 'id=1'
# ====== HDFS的配置 ======
--target-dir /user/company
--delete-target-dir
--num-mappers 1
--fields-terminated-by "t"
MySQL --> Hive
Sqoop从MySQL导入到Hive中,分为两步:
- 创建一个临时目录存放从MySQL上导入的数据,默认目录为:/user/{mysqlTableName}/
- 将临时目录的数据迁移到Hive表目录中,迁移完毕删除临时目录
bin/sqoop import
# ====== MySQL的配置 ======
--connect jdbc:mysql://hadoop102:3306/company
--username root
--password 123456
--table staff
# ====== HDFS的配置 ======
--delete-target-dir
--num-mappers 1
--fields-terminated-by "t"
# ====== Hive的配置 ======
# --hive-import:把从MySQL导入到临时目录的数据迁移到Hive表目录
--hive-import
--hive-overwrite
--hive-table staff_hive
注意:如果抛出异常:Could not load org.apache.hadoop.hive.conf.HiveConf. Make sure HIVE_CONF_DIR is set correctly,则需要$HIVE_HOME/lib/*加入到环境变量HADOOP_CLASSPATH中。在sqopp-env.sh下添加如下代码:
代码语言:javascript复制export HADOOP_CLASSPATH=$HADOOP_CLASSPATH:$HIVE_HOME/lib/*
问题:Sqoop1.4.6会自动创建Hive表,Sqoop1.4.7可能与Hive1.2.2版本不兼容,不会自动创建Hive表,虽然已经把数据导入到指定创建的Hive表目录下,但是没有添加元数据,在Hive中查询不到该表。
解决方法:把Hive的hive-site.xml拷贝到Sqoop的conf目录。
MySQL --> HBase
Sqoop可以直接从MySQL把数据导入到HBase中,不像Hive有个--hive-import需要分为两步执行。像Sqoop、Oozie要和很多框架进行交互,所以它们和其他框架的版本兼容性就非常重要,所以公司中一般使用cdh版本,cdh版本把版本兼容性全部搞定,不需要我们再操心这些事情!
代码语言:javascript复制bin/sqoop import
# ====== MySQL的配置 ======
--connect jdbc:mysql://hadoop102:3306/company
--username root
--password 123456
--table staff
--columns id,name,sex
# ====== HBase的配置 ======
--hbase-table hbase_company
--hbase-row-key id
--column-family info
# Column of the table userd to split work units 测试后发现不加也不影响导入
--split-by id
--hbase-create-table
--num-mappers 1
HDFS-->MySQL
代码语言:javascript复制bin/sqoop export
# ====== MySQL的配置 ======
--connect jdbc:mysql://hadoop102:3306/company
--username root
--password 123456
--table staff
# ====== HDFS的配置 ======
--num-mappers 1
# 导出目录,这样看是不是HDFS和Hive没区别?
--export-dir /user/hive/warehouse/staff_hive
# --update-key:表示所有操作变成update ... 操作
# 但是,如果原来表中不存在的id则不会插入进去,只会更新
--update-key id
# --update-mode allowinsert:表示存在的就更新,不存在的就插入
--update-mode allowinsert
# 必须指定分隔符、否则默认不分隔,导出到MySQL会解析错误(可能把一整行字符串当做主键插入)
--input-fields-terminated-by "t"
注意:MySQL中的staff表必须提前存在,否则会抛出异常。由于MySQL的数据类型很多,导出的时候Sqoop不知道该怎么给MySQL的列定义类型,必须我们自己提前创建表,指定MySQL列的类型,所以导出之前MySQL的表必须存在。
Hive数据本来就在HDFS上,所以Hive导出到MySQL和上述方法一样。
05
Sqoop的遗憾
Apache Sqoop moved into the Attic in 2021-06. Apache Sqoop mission was the creation and maintenance of software related to Bulk Data Transfer for Apache Hadoop and Structured Datastores.
这款很多人都用过的工具,从Apache顶级项目列表中“下架”了,相信现在还有很多公司在使用的。其实很多开源项目并不是因为它不够优秀,有时候可能是没有商业公司运营推广,像Spark,Flink,包括国人的顶级项目Kylin,背后都有商业公司在运营推广。
资本的力量很强大!
希望大家能够在用到好的开源项目的时候能够给予一定的贡献,哪怕是贡献一个想法,修改一处文档也可以。这里有之前写的一份如何参与Apache项目的指南《如何参与一个Apache开源项目》,一起加入开源!
开源,让技术更美好!