Sqoop原理篇

1 Sqoop簡介

      Apache Sqoop(SQL-to-Hadoop)項目旨在協助RDBMS與Hadoop之間進行高效的大數據交流。用戶可以在 Sqoop 的幫助下,輕鬆地把關係型數據庫的數據導入到 Hadoop 與其相關的系統 (如HBase和Hive)中;同時也可以把數據從 Hadoop 系統裏抽取並導出到關係型數據庫裏。
      Sqoop是一個在結構化數據和Hadoop之間進行批量數據遷移的工具,結構化數據可以是MySQL、Oracle等RDBMS。Sqoop底層用MapReduce程序實現抽取、轉換、加載,MapReduce天生的特性保證了並行化和高容錯率,而且相比Kettle等傳統ETL工具,任務跑在Hadoop集羣上,減少了ETL服務器資源的使用情況。在特定場景下,抽取過程會有很大的性能提升。
      如果要用Sqoop,必須正確安裝並配置Hadoop,因依賴於本地的Hadoop環境啓動MR程序;MySQL、Oracle等數據庫的JDBC驅動也要放到Sqoop的lib目錄下。

2 Sqoop架構

2.1 Sqoop1和Sqoop2的對比

(1)Sqoop1架構 在這裏插入圖片描述
(2)Sqoop2架構 在這裏插入圖片描述
(3)對比分析
      ① 在架構上,Sqoop1僅僅使用一個Sqoop客戶端;Sqoop2引入了Sqoop Server,對Connector實現了集中的管理,其訪問方式也變得多樣化了,其可以通過REST API、JAVA API、WEB UI以及CLI控制檯方式進行訪問。
      ② 在安全性能方面,在Sqoop1中我們經常用腳本的方式將HDFS中的數據導入到MySQL中,或者反過來將MySQL數據導入到HDFS中,其中在腳本里邊都要顯示指定MySQL數據庫的用戶名和密碼的,安全性做的不是太完善。在Sqoop2中,如果是通過CLI方式訪問的話,會有一個交互過程界面,你輸入的密碼信息不被看到,同時Sqoop2引入基於角色的安全機制。
(4)優缺點
      ① Sqoop1優點:架構部署簡單;
      ② Sqoop1缺點:命令行方式容易出錯,格式緊耦合,無法支持所有數據類型,安全機制不夠完善,例如密碼暴漏,安裝需要root權限,connector必須符合JDBC模型;
      ③ Sqoop2優點:多種交互方式,命令行,Web UI,REST API,Conncetor集中化管理,所有的鏈接安裝在Sqoop Server上,完善權限管理機制,Connector規範化,僅僅負責數據的讀寫;
      ④ Sqoop2缺點:架構稍複雜,配置部署更繁瑣。

2.2 Sqoop2數據導入

將數據從關係型數據庫導入到Hadoop中
      Step1:Sqoop與數據庫Server通信,獲取數據庫表的元數據信息;
      Step2:Sqoop啓動一個Map-Only的MR作業,利用元數據信息並行將數據寫入Hadoop。
      Sqoop在import時,需要制定split-by參數。Sqoop根據不同的split-by參數值來進行切分,然後將切分出來的區域分配到不同map中。每個map中再處理數據庫中獲取的一行一行的值,寫入到HDFS中。同時split-by根據不同的參數類型有不同的切分方法,如比較簡單的int型,Sqoop會取最大和最小split-by字段值,然後根據傳入的num-mappers來確定劃分幾個區域。 比如select max(split_by),min(split-by) from得到的max(split-by)和min(split-by)分別爲1000和1,而num-mappers爲2的話,則會分成兩個區域(1,500)和(501-100),同時也會分成2個sql給2個map去進行導入操作,分別爲select XXX from table where split-by>=1 and split-by<500和select XXX from table where split-by>=501 and split-by<=1000。最後每個map各自獲取各自SQL中的數據進行導入工作。
在這裏插入圖片描述

2.2.1 Sqoop大概流程

(1)讀取要導入數據的表結構,生成運行類,默認是QueryResult,打成jar包,然後提交給Hadoop;
(2)設置好job,主要也就是設置好各個參數
(3)這裏就由Hadoop來執行MapReduce來執行Import命令
      ① 首先要對數據進行切分,也就是DataSplit,DataDrivenDBInputFormat.getSplits(JobContext job)
      ② 切分好範圍後,寫入範圍,以便讀取DataDrivenDBInputFormat.write(DataOutput output),這裏是lowerBoundQuery and upperBoundQuery
      ③ 讀取以上②)寫入的範圍DataDrivenDBInputFormat.readFields(DataInput input)
      ④ 然後創建RecordReader從數據庫中讀取數據DataDrivenDBInputFormat.createRecordReader(InputSplit split,TaskAttemptContext context)
      ⑤ 創建MAP,MapTextImportMapper.setup(Context context)
      ⑥ RecordReader一行一行從關係型數據庫中讀取數據,設置好Map的Key和Value,交給MapDBRecordReader.nextKeyValue()
      ⑦ 運行MAP,mapTextImportMapper.map(LongWritable key, SqoopRecord val, Context context),最後生成的Key是行數據,由QueryResult生成,Value是NullWritable.get()
(4)導入控制
      Sqoop不需要每次都導入整張表。例如,可以指定導入表的部分列。用戶也可以在查詢中加入WHERE子句(使用—where參數),以此來限定需要導入的記錄。
(5)導入和一致性
      在向HDFS導入數據時,重要的是要確保訪問的是數據源的一致性快照。保證一致性的最好方法是在導入時不允許運行任何對錶中現有數據進行更新的進程。
(6)增量導入
      定期運行導入時一種很常見的方式,這樣做可以使HDFS的數據與數據庫的數據保持同步。爲此需要識別哪些是新數據。對於某一行來說,只有當特定列(由—check-column參數指定)的值大於指定值(通過—last-value設置)時,Sqoop纔會導入該行數據。
(7)直接模式導入
      在Sqoop的文檔中將使用外部工具的方法稱爲直接模式。
(8)導入大對象
      “內聯”存儲大對象,它們會嚴重影響掃描的性能。因此將大對象與它們的行分開存儲,如下圖:
在這裏插入圖片描述
      由於大對象單條記錄太大,無法在內存中實現物化。爲了克服這個困難,當導入大對象數據大於閾值16M時(通過sqoop.inline.lob.length.max設置,以字節爲單位),Sqoop將導入的大對象存儲在LobFile格式的單獨文件中。LobFile格式能夠存儲非常大的單條記錄(使用了64位的地址空間),每條記錄保存一個大對象。LobFile格式允許客戶端持有對記錄的引用,而不訪問記錄內容,對記錄的訪問通過java.io.InputStream(用於二進制對象)或java.io.Reader(用於字符對象)來實現的。在導入一條記錄時,所有的“正常”字段會在一個文本文件中一起被物化,同時還生成一個指向保存CLOB或BLOB列的LobFile文件的引用。

2.3 Sqoop2數據導出

在這裏插入圖片描述
      Sqoop導出功能的架構與其導入功能非常相似,在執行導出操作之前,Sqoop會根據數據庫連接字符串來選擇一個導出方法。一般爲jdbc。然後,Sqoop會根據目標表的定義生成一個java類。這個生成的類能夠從文本文件中解析記錄,並能夠向表中插入類型合適的值。接着會啓動一個MapReduce作業,從HDFS中讀取源數據文件,使用生成的類解析記錄,並且執行選定的導出方法。
基於jdbc的導出方法會產生一批insert語句,每條語句都會向目標表中插入多條記錄。多個單獨的線程被用於從HDFS讀取數據並與數據庫進行通信,以確保涉及不同系統的I/O操作能夠儘可能重疊執行。
雖然HDFS讀取數據的MapReduce作業大多根據所處理文件的數量和大小來選擇並行度(Map任務的數量),但Sqoop的導出工具允許用戶明確設定任務的數量。由於導出性能會受並行的數據庫寫入線程數量的影響,所以Sqoop使用CombineFileInput類將輸入文件分組分配給少數幾個Map任務去執行。
(1)導出與實務
      進程的並行特性,導致導出操作往往不是原子操作。Sqoop會採用多個並行的任務導出,並且數據庫系統使用固定大小的緩衝區來存儲事務數據,這時一個任務中的所有操作不可能在一個事務中完成。因此,在導出操作進行過程中,提交過的中間結果都是可見的。在導出過程完成前,不要啓動那些使用導出結果的應用程序,否則這些應用會看到不完整的導出結果。
      爲了解決這個問題,Sqoop可以先將數據導出到一個臨時階段表中,然後在導出任務完成前(即導出操作成功執行後),在一個事務中將臨時階段表中的數據全部移動到目標表中。使用臨時階段表會降低執行速度,因爲它需要寫兩次數據:先寫入臨時階段表,再寫入目標表。整個導出過程運行所使用的的空間也更多,因爲從臨時階段表向目標表導出時存在數據的兩個複本。
(2)導出與SequenceFile
      Sqoop還可以將存儲在SequenceFile中的記錄導出到輸出表,不過有一些限制。SequenceFile中可以保存任意類型的記錄。Sqoop的導出工具從SequenceFile中讀取對象,然後直接發送到OutputCollector,由它將這些對象傳遞給數據庫導出OutputFormat。爲了能讓Sqoop使用,記錄必須被保存在SequenceFile鍵值對格式的值部分,並且必須繼承抽象類com.cloudera.sqoop.lib.SqoopRecord。

參考文章:
[1]《Hadoop權威指南》
[2] https://www.liangzl.com/get-article-detail-8271.html
[3] https://www.biaodianfu.com/sqoop.html
[4] https://www.jianshu.com/p/dd723351b39e

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