sqoop學習



 Sqoop 是傳統數據庫與 Hadoop 之間數據同步的工具,它是 Hadoop 發展到一定程度的必然產物,它主要解決的是傳統數據庫和Hadoop之間數據的遷移問題。這節課我們將詳細介紹 Sqoop 這個工具。

Sqoop 產生背景

        Sqoop 的產生主要源於以下幾種需求:

        1、多數使用 Hadoop 技術處理大數據業務的企業,有大量的數據存儲在傳統的關係型數據庫(RDBMS)中。

        2、由於缺乏工具的支持,對 Hadoop 和 傳統數據庫系統中的數據進行相互傳輸是一件十分困難的事情。

        3、基於前兩個方面的考慮,亟需一個在 RDBMS 與 Hadoop 之間進行數據傳輸的項目。

Sqoop 是什麼

        Sqoop 是連接傳統關係型數據庫和 Hadoop 的橋樑。它包括以下兩個方面:

        1、 將關係型數據庫的數據導入到 Hadoop 及其相關的系統中,如 Hive和HBase。

        2、 將數據從 Hadoop 系統裏抽取並導出到關係型數據庫。

        Sqoop 的核心設計思想是利用 MapReduce 加快數據傳輸速度。也就是說 Sqoop 的導入和導出功能是通過 MapReduce 作業實現的。所以它是一種批處理方式進行數據傳輸,難以實現實時的數據進行導入和導出。

爲什麼選擇 Sqoop

        我們爲什麼選擇 Sqoop 呢?通常基於三個方面的考慮:

        1、它可以高效、可控地利用資源,可以通過調整任務數來控制任務的併發度。另外它還可以配置數據庫的訪問時間等等。

        2、它可以自動的完成數據類型映射與轉換。我們往往導入的數據是有類型的,它可以自動根據數據庫中的類型轉換到 Hadoop 中,當然用戶也可以自定義它們之間的映射關係。

        3、它支持多種數據庫,比如,Mysql、Oracle和PostgreSQL等等數據庫。

Sqoop 安裝

        我們 Hadoop 集羣安裝的是 Hadoop2.2.0 版本,所以 Sqoop 安裝版本也要與之相匹配,否則後面 Sqoop 工具的使用會出現問題。這裏我們選擇 sqoop-1.4.6.bin__hadoop-2.0.4-alpha.tar.gz版本安裝。 安裝 Sqoop 很簡單,分爲以下幾步完成。

        1、首先將下載的 sqoop-1.4.6.bin__hadoop-2.0.4-alpha.tar.gz放到 /usr/java/目錄下,然後對安裝包解壓、修改文件名和修改用戶權限。

[root@single-hadoop-dajiangtai-com java]# tar zxvf sqoop-1.4.6.bin__hadoop-1.0.0.tar.gz //解壓
[root@single-hadoop-dajiangtai-com java]# rm sqoop-1.4.6.bin__hadoop-1.0.0.tar.gz //刪除安裝包
[root@single-hadoop-dajiangtai-com java]# mv sqoop-1.4.6.bin__hadoop-1.0.0 sqoop //修改安裝文件目錄
[root@single-hadoop-dajiangtai-com java]# chown -R hadoop:hadoop sqoop //賦予sqoop hadoop用戶權限

        2、切換到/sqoop/conf 目錄下,執行以下命令。

[hadoop@single-hadoop-dajiangtai-com java]$ cd sqoop/conf
[hadoop@single-hadoop-dajiangtai-com 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,反之,不用配置。

        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@single-hadoop-dajiangtai-com lib]$ cp commons-cli-1.2.jar /usr/java/sqoop/lib
[hadoop@single-hadoop-dajiangtai-com common]$ cp hadoop-common-2.2.0.jar /usr/java/sqoop/lib
[hadoop@single-hadoop-dajiangtai-com mapreduce]$ cp hadoop-mapreduce-client-core-2.2.0.jar /usr/java/sqoop/lib
[hadoop@single-hadoop-dajiangtai-com java]$ cp mysql-connector-java-5.1.21.jar /usr/java/sqoop/lib

        4、添加環境變量。

[hadoop@single-hadoop-dajiangtai-com java]$ vi ~/.bash_profile
PATH=$PATH:$HOME/bin
export SQOOP_HOME=/usr/java/sqoop //sqoop安裝目錄
export PATH=$PATH:$SQOOP_HOME/bin

        環境添加完畢後,執行以下命令使環境生效。

[hadoop@single-hadoop-dajiangtai-com java]$ source ~/.bash_profile

        5、測試運行

[hadoop@single-hadoop-dajiangtai-com java]$ sqoop list-databases \
> --connect jdbc:mysql://db.dajiangtai.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
djtdb_demo
djtdb_hadoop
djtdb_www

        sqoop 命令執行成功,代表安裝成功。




Sqoop 架構

        Sqoop 架構是非常簡單的,它主要由三個部分組成:Sqoop client、HDFS/HBase/Hive、Database。下面我們來看一下 Sqoop 的架構圖。

sqoop 架構圖

        用戶向 Sqoop 發起一個命令之後,這個命令會轉換爲一個基於 Map Task 的 MapReduce 作業。Map Task 會訪問數據庫的元數據信息,通過並行的 Map Task 將數據庫的數據讀取出來,然後導入 Hadoop 中。 當然也可以將 Hadoop 中的數據,導入傳統的關係型數據庫中。它的核心思想就是通過基於 Map Task (只有 map)的 MapReduce 作業,實現數據的併發拷貝和傳輸,這樣可以大大提高效率。

Sqoop與HDFS結合

        下面我們結合 HDFS,介紹 Sqoop 從關係型數據庫的導入和導出。

Sqoop import

        它的功能是將數據從關係型數據庫導入 HDFS 中,其流程圖如下所示。

sqoop import

        我們來分析一下 Sqoop 數據導入流程,首先用戶輸入一個 Sqoop import 命令,Sqoop 會從關係型數據庫中獲取元數據信息,比如要操作數據庫表的 schema是什麼樣子,這個表有哪些字段,這些字段都是什麼數據類型等。它獲取這些信息之後,會將輸入命令轉化爲基於 Map 的 MapReduce作業。這樣 MapReduce作業中有很多 Map 任務,每個 Map 任務從數據庫中讀取一片數據,這樣多個 Map 任務實現併發的拷貝,把整個數據快速的拷貝到 HDFS 上。

        下面我們看一下 Sqoop 如何使用命令行來導入數據的,其命令行語法如下所示。

sqoop import \
--connect jdbc:mysql://db.dajiangtai.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,會佔用很大的空間。

        下面我們介紹幾種 Sqoop 數據導入的特殊應用。

        1、Sqoop 每次導入數據的時候,不需要把以往的所有數據重新導入 HDFS,只需要把新增的數據導入 HDFS 即可,下面我們來看看如何導入新增數據。

sqoop import \
--connect jdbc:mysql://db.dajiangtai.net:3306/djtdb_hadoop \
--username sqoop \
--password sqoop \
--table user \
--incremental append \ //代表只導入增量數據
--check-column id \ //以主鍵id作爲判斷條件
--last-value 999 //導入id大於999的新增數據

        上述三個組合使用,可以實現數據的增量導入。

        2、Sqoop 數據導入過程中,直接輸入明碼存在安全隱患,我們可以通過下面兩種方式規避這種風險。

        1)-P:sqoop 命令行最後使用 -P,此時提示用戶輸入密碼,而且用戶輸入的密碼是看不見的,起到安全保護作用。密碼輸入正確後,纔會執行 sqoop 命令。

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

        2)--password-file:指定一個密碼保存文件,讀取密碼。我們可以將這個文件設置爲只有自己可讀的文件,防止密碼泄露。

sqoop import \
--connect jdbc:mysql://db.dajiangtai.net:3306/djtdb_hadoop \
--username sqoop \
--table user \
--password-file my-sqoop-password

Sqoop export

        它的功能是將數據從 HDFS 導入關係型數據庫表中,其流程圖如下所示。

sqoop export

        我們來分析一下 Sqoop 數據導出流程,首先用戶輸入一個 Sqoop export 命令,它會獲取關係型數據庫的 schema,建立 Hadoop 字段與數據庫表字段的映射關係。 然後會將輸入命令轉化爲基於 Map 的 MapReduce作業,這樣 MapReduce作業中有很多 Map 任務,它們並行的從 HDFS 讀取數據,並將整個數據拷貝到數據庫中。

        下面我們看一下 Sqoop 如何使用命令行來導出數據的,其命令行語法如下所示。

sqoop export \
--connect jdbc:mysql://db.dajiangtai.net:3306/djtdb_hadoop \
--username sqoop \
--password sqoop \
--table user \
--export-dir user

        --connect:指定 JDBC URL。

        --username/password:mysql 數據庫的用戶名和密碼。

        --table:要導入的數據庫表。

        --export-dir:數據在 HDFS 上的存放目錄。

        下面我們介紹幾種 Sqoop 數據導出的特殊應用。

        1、Sqoop export 將數據導入數據庫,一般情況下是一條一條導入的,這樣導入的效率非常低。這時我們可以使用 Sqoop export 的批量導入提高效率,其具體語法如下。

sqoop export \
--Dsqoop.export.records.per.statement=10 \
--connect jdbc:mysql://db.dajiangtai.net:3306/djtdb_hadoop \
--username sqoop \
--password sqoop \
--table user \
--export-dir user \
--batch

        --Dsqoop.export.records.per.statement:指定每次導入10條數據,--batch:指定是批量導入。

        2、在實際應用中還存在這樣一個問題,比如導入數據的時候,Map Task 執行失敗, 那麼該 Map 任務會轉移到另外一個節點執行重新運行,這時候之前導入的數據又要重新導入一份,造成數據重複導入。 因爲 Map Task 沒有回滾策略,一旦運行失敗,已經導入數據庫中的數據就無法恢復。Sqoop export 提供了一種機制能保證原子性, 使用--staging-table 選項指定臨時導入的表。Sqoop export 導出數據的時候會分爲兩步:第一步,將數據導入數據庫中的臨時表,如果導入期間 Map Task 失敗,會刪除臨時表數據重新導入;第二步,確認所有 Map Task 任務成功後,會將臨時表名稱爲指定的表名稱。

sqoop export \
--connect jdbc:mysql://db.dajiangtai.net:3306/djtdb_hadoop \
--username sqoop \
--password sqoop \
--table user \
--staging-table staging_user

        3、在 Sqoop 導出數據過程中,如果我們想更新已有數據,可以採取以下兩種方式。

        1)通過 --update-key id 更新已有數據。

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

        2)使用 --update-key id和--update-mode allowinsert 兩個選項的情況下,如果數據已經存在,則更新數據,如果數據不存在,則插入新數據記錄。

sqoop export \
--connect jdbc:mysql://db.dajiangtai.net:3306/djtdb_hadoop \
--username sqoop \
--password sqoop \
--table user \
--update-key id \
--update-mode allowinsert

        4、如果 HDFS 中的數據量比較大,很多字段並不需要,我們可以使用 --columns 來指定插入某幾列數據。

sqoop export \
--connect jdbc:mysql://db.dajiangtai.net:3306/djtdb_hadoop \
--username sqoop \
--password sqoop \
--table user \
--column username,sex

        5、當導入的字段數據不存在或者爲null的時候,我們使用--input-null-string和--input-null-non-string 來處理。

sqoop export \
--connect jdbc:mysql://db.dajiangtai.net:3306/djtdb_hadoop \
--username sqoop \
--password sqoop \
--table user \
--input-null-string '\\N' \
--input-null-non-string '\\N'

Sqoop與其它系統結合

        Sqoop 也可以與Hive、HBase等系統結合,實現數據的導入和導出,用戶需要在 sqoop-env.sh 中添加HBASE_HOME、HIVE_HOME等環境變量。

        1、Sqoop與Hive結合比較簡單,使用 --hive-import 選項就可以實現。

sqoop import \
--connect jdbc:mysql://db.dajiangtai.net:3306/djtdb_hadoop \
--username sqoop \
--password sqoop \
--table user \
--hive-import

        2、Sqoop與HBase結合稍微麻煩一些,需要使用 --hbase-table 指定表名稱,使用 --column-family 指定列名稱。

sqoop import \
--connect jdbc:mysql://db.dajiangtai.net:3306/djtdb_hadoop \
--username sqoop \
--password sqoop \
--table user \
--hbase-table user \
--column-family city



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章