介绍与部署

Sqoop

Sqoop 是连接传统关系型数据库和 Hadoop 的桥梁。它包括以下两个方面:    1、将关系型数据库的数据导入到 Hadoop 及其相关的系统中,如 Hive 和 HBase。    2、将数据从 Hadoop 系统里抽取并导出到关系型数据库。 Sqoop 的核心设计思想是利用 MapReduce 加快数据传输速度。也就是说 Sqoop 的导入和导出功能是通过 MapReduce 作业实现的。所以它是一种批处理方式进行数据传输,难以实现实时的数据进行导入和导出。 我们为什么选择 Sqoop 呢?通常基于三个方面的考虑:    1、它可以高效、可控地利用资源,可以通过调整任务数来控制任务的并发度。另外它还可以配置数据库的访问时间等等。    2、它可以自动的完成数据类型映射与转换。我们往往导入的数据是有类型的,它可以自动根据数据库中的类型转换到 Hadoop 中,当然用户也可以自定义它们之间的映射关系。    3、它支持多种数据库,比如,MySQL、Oracle 和 PostgreSQL 等等数据库。

Architecture

Sqoop 架构是非常简单的,它主要由三个部分组成:Sqoop client、HDFS/HBase/Hive、Database。下面我们来看一下 Sqoop 的架构图。

用户向 Sqoop 发起一个命令之后,这个命令会转换为一个基于 Map Task 的 MapReduce 作业。Map Task 会访问数据库的元数据信息,通过并行的 Map Task 将数据库的数据读取出来,然后导入 Hadoop 中。当然也可以将 Hadoop 中的数据,导入传统的关系型数据库中。它的核心思想就是通过基于 Map Task (只有 map)的 MapReduce 作业,实现数据的并发拷贝和传输,这样可以大大提高效率。

Quick Start

我们 Hadoop 集群安装的是 Hadoop2.2.0 版本,所以 Sqoop 安装版本也要与之相匹配,否则后面 Sqoop 工具的使用会出现问题。这里我们选择 sqoop-1.4.6.binhadoop-2.0.4-alpha.tar.gz 版本安装。安装 Sqoop 很简单,分为以下几步完成。 1、首先将下载的 sqoop-1.4.6.binhadoop-2.0.4-alpha.tar.gz 放到 /usr/java/目录下,然后对安装包解压、修改文件名和修改用户权限。

[root@cs0 java]# tar zxvf sqoop-1.4.6.bin__hadoop-1.0.0.tar.gz //解压
[root@cs0 java]# rm sqoop-1.4.6.bin__hadoop-1.0.0.tar.gz //删除安装包
[root@cs0 java]# mv sqoop-1.4.6.bin__hadoop-1.0.0 sqoop //修改安装文件目录
[root@cs0 java]# chown -R hadoop:hadoop sqoop //赋予sqoop hadoop用户权限12341234

2、切换到/sqoop/conf 目录下,执行以下命令。

[hadoop@cs0 java]$ cd sqoop/conf
[hadoop@cs0 java]$ mv sqoop-env-template.sh sqoop-env.sh
        然后使用 vi sqoop-env.sh 命令,打开文件添加如下内容。
#Set path to where bin/hadoop is available
export HADOOP_COMMON_HOME=/usr/java/hadoop-2.2.0-x64
#Set path to where hadoop-*-core.jar is available
export HADOOP_MAPRED_HOME=/usr/java/hadoop-2.2.0-x64
#set the path to where bin/hbase is available
#export HBASE_HOME=
#Set the path to where bin/hive is available
export HIVE_HOME=/usr/java/hive-1.0.0
#Set the path for where zookeper config dir is
#export ZOOCFGDIR=
        如果数据读取不涉及hbase和hive,那么相关hbase和hive的配置可以不加;如果集群有独立的zookeeper集群,那么配置zookeeper,反之,不用配置。12345678910111213141234567891011121314

3、将相关的驱动 jar 包拷贝到 sqoop/lib 目录下。安装 Hadoop2.2.0 的核心 jar 包有三个需要导入:commons-cli-1.2.jar、hadoop-common-2.2.0.jar 和 hadoop- mapreduce-client-core-2.2.0.jar。数据库驱动 jar 包需要导入,这里我们使用的是 mysql 数据库,所以需要导入 mysql-connector-java-5.1.21.jar 包。

[hadoop@cs0 lib]$ cp commons-cli-1.2.jar /usr/java/sqoop/lib
[hadoop@cs0 common]$ cp hadoop-common-2.2.0.jar /usr/java/sqoop/lib
[hadoop@cs0 mapreduce]$ cp hadoop-mapreduce-client-core-2.2.0.jar /usr/java/sqoop/lib
[hadoop@cs0 java]$ cp mysql-connector-java-5.1.21.jar /usr/java/sqoop/lib12341234

4、添加环境变量。

 [hadoop@cs0 java]$ vi ~/.bash_profile
PATH=$PATH:$HOME/bin
export SQOOP_HOME=/usr/java/sqoop //sqoop安装目录
export PATH=$PATH:$SQOOP_HOME/bin
        环境添加完毕后,执行以下命令使环境生效。
[hadoop@cs0 java]$ source ~/.bash_profile     123456123456

5、测试运行

[hadoop@cs0 java]$ sqoop list-databases \
> --connect jdbc:mysql://db.ywendeng.net:3306/djtdb_hadoop \
> --username sqoop \
> --password sqoop
15/06/03 02:47:27 INFO sqoop.Sqoop: Running Sqoop version: 1.4.6
15/06/03 02:47:27 WARN tool.BaseSqoopTool: Setting your password on the command-line is insecure. Consider using -P instead.
15/06/03 02:47:28 INFO manager.MySQLManager: Preparing to use a MySQL streaming resultset.
information_schema
        sqoop 命令执行成功,代表安装成功。

Usage

  • Sqoop 与 HDFS 结合

    下面我们结合 HDFS,介绍 Sqoop 从关系型数据库的导入和导出。 Sqoop import   它的功能是将数据从关系型数据库导入 HDFS 中,其流程图如下所示。   

    这里写图片描述
       我们来分析一下 Sqoop 数据导入流程,首先用户输入一个 Sqoop import 命令,Sqoop 会从关系型数据库中获取元数据信息,比如要操作数据库表的 schema 是什么样子,这个表有哪些字段,这些字段都是什么数据类型等。它获取这些信息之后,会将输入命令转化为基于 Map 的 MapReduce 作业。这样 MapReduce 作业中有很多 Map 任务,每个 Map 任务从数据库中读取一片数据,这样多个 Map 任务实现并发的拷贝,把整个数据快速的拷贝到 HDFS 上。    下面我们看一下 Sqoop 如何使用命令行来导入数据的,其命令行语法如下所示。

sqoop import \
--connect jdbc:mysql://db.ywendeng.net:3306/djtdb_hadoop \
--username sqoop \
--password sqoop \
--table user \
--target-dir /junior/sqoop/ \       //可选,不指定目录,数据默认导入到/user下
--where "sex='female'" \    //可选
--as-sequencefile \     //可选,不指定格式,数据格式默认为 Text 文本格式
--num-mappers 10 \      //可选,这个数值不宜太大
--null-string '\\N' \       //可选
--null-non-string '\\N' \       //可选
        --connect:指定 JDBC URL。
        --username/password:mysql 数据库的用户名。
        --table:要读取的数据库表。
        --target-dir:将数据导入到指定的 HDFS 目录下,文件名称如果不指定的话,会默认数据库的表名称。
        --where:过滤从数据库中要导入的数据。
        --as-sequencefile:指定数据导入数据格式。
        --num-mappers:指定 Map 任务的并发度。
        --null-string,--null-non-string:同时使用可以将数据库中的空字段转化为'\N',因为数据库中字段为 null,会占用很大的空间。1234567891011121314151617181912345678910111213141516171819

下面我们介绍几种 Sqoop 数据导入的特殊应用。 1、Sqoop 每次导入数据的时候,不需要把以往的所有数据重新导入 HDFS,只需要把新增的数据导入 HDFS 即可,下面我们来看看如何导入新增数据。

sqoop import \
--connect jdbc:mysql://db.ywendeng.net:3306/djtdb_hadoop \
--username sqoop \
--password sqoop \
--table user \
--incremental append \      //代表只导入增量数据
--check-column id \         //以主键id作为判断条件
--last-value 999        //导入id大于999的新增数据
        上述三个组合使用,可以实现数据的增量导入。123456789123456789

2、Sqoop 数据导入过程中,直接输入明码存在安全隐患,我们可以通过下面两种方式规避这种风险。    1)-P:sqoop 命令行最后使用 -P,此时提示用户输入密码,而且用户输入的密码是看不见的,起到安全保护作用。密码输入正确后,才会执行 sqoop 命令。

sqoop import \
--connect jdbc:mysql://db.ywendeng.net:3306/djtdb_hadoop \
--username sqoop \
--table user \
-P1234512345

2)–password-file:指定一个密码保存文件,读取密码。我们可以将这个文件设置为只有自己可读的文件,防止密码泄露。

sqoop import \
--connect jdbc:mysql://db.ywendeng.net:3306/csdb_hadoop \
--username sqoop \
--table user \
--password-file my-sqoop-password1234512345

Sqoop export    它的功能是将数据从 HDFS 导入关系型数据库表中,其流程图如下所示。   

这里写图片描述
  我们来分析一下 Sqoop 数据导出流程,首先用户输入一个 Sqoop export 命令,它会获取关系型数据库的 schema,建立 Hadoop 字段与数据库表字段的映射关系。然后会将输入命令转化为基于 Map 的 MapReduce 作业,这样 MapReduce 作业中有很多 Map 任务,它们并行的从 HDFS 读取数据,并将整个数据拷贝到数据库中。      下面我们看一下 Sqoop 如何使用命令行来导出数据的,其命令行语法如下所示。

sqoop export \
--connect jdbc:mysql://db.ywendeng.net:3306/csdb_hadoop \
--username sqoop \
--password sqoop \
--table user \
--export-dir user
        --connect:指定 JDBC URL。
        --username/password:mysql 数据库的用户名和密码。
        --table:要导入的数据库表。
        --export-dir:数据在 HDFS 上的存放目录。1234567891012345678910

下面我们介绍几种 Sqoop 数据导出的特殊应用。    1、Sqoop export 将数据导入数据库,一般情况下是一条一条导入的,这样导入的效率非常低。这时我们可以使用 Sqoop export 的批量导入提高效率,其具体语法如下。

sqoop export \
--Dsqoop.export.records.per.statement=10 \
--connect jdbc:mysql://db.ywendeng.net:3306/csdb_hadoop \
--username sqoop \
--password sqoop \
--table user \
--export-dir user \
--batch
        --Dsqoop.export.records.per.statement:指定每次导入10条数据,--batch:指定是批量导入。123456789123456789

2、在实际应用中还存在这样一个问题,比如导入数据的时候,Map Task 执行失败,那么该 Map 任务会转移到另外一个节点执行重新运行,这时候之前导入的数据又要重新导入一份,造成数据重复导入。因为 Map Task 没有回滚策略,一旦运行失败,已经导入数据库中的数据就无法恢复。Sqoop export 提供了一种机制能保证原子性,使用–staging-table 选项指定临时导入的表。Sqoop export 导出数据的时候会分为两步:第一步,将数据导入数据库中的临时表,如果导入期间 Map Task 失败,会删除临时表数据重新导入;第二步,确认所有 Map Task 任务成功后,会将临时表名称为指定的表名称。

sqoop export \
--connect jdbc:mysql://db.ywendeng.net:3306/csdb_hadoop \
--username sqoop \
--password sqoop \
--table user \
--staging-table staging_user 123456123456

3、在 Sqoop 导出数据过程中,如果我们想更新已有数据,可以采取以下两种方式。    1)通过 –update-key id 更新已有数据。

sqoop export \
--connect jdbc:mysql://db.ywendeng.net:3306/csdb_hadoop \
--username sqoop \
--password sqoop \
--table user \
--update-key id 123456123456

2)使用 –update-key id 和–update-mode allowinsert 两个选项的情况下,如果数据已经存在,则更新数据,如果数据不存在,则插入新数据记录。

sqoop export \
--connect jdbc:mysql://db.ywendeng.net:3306/csdb_hadoop \
--username sqoop \
--password sqoop \
--table user \
--update-key id \
--update-mode allowinsert12345671234567

4、如果 HDFS 中的数据量比较大,很多字段并不需要,我们可以使用 –columns 来指定插入某几列数据。

sqoop export \
--connect jdbc:mysql://db.ywendeng.net:3306/csdb_hadoop \
--username sqoop \
--password sqoop \
--table user \
--column username,sex123456123456

5、当导入的字段数据不存在或者为 null 的时候,我们使用–input-null-string 和–input-null-non-string 来处理。

sqoop export \
--connect jdbc:mysql://db.ywendeng.net:3306/csdb_hadoop \
--username sqoop \
--password sqoop \
--table user \
--input-null-string '\\N' \
--input-null-non-string '\\N'12345671234567
  • Sqoop 与其它系统结合

    Sqoop 也可以与 Hive、HBase 等系统结合,实现数据的导入和导出,用户需要在 sqoop-env.sh 中添加 HBASE_HOME、HIVE_HOME 等环境变量。

    1、Sqoop 与 Hive 结合比较简单,使用 –hive-import 选项就可以实现。

sqoop import \
--connect jdbc:mysql://db.ywendeng.net:3306/csdb_hadoop \
--username sqoop \
--password sqoop \
--table user \
--hive-import123456123456

2、Sqoop 与 HBase 结合稍微麻烦一些,需要使用 –hbase-table 指定表名称,使用 –column-family 指定列名称。