【原創】修改Sqoop1.4.6源碼實現--fields-terminated-by選項支持多字節分隔符


修改Sqoop1.4.6源碼實現--fields-terminated-by選項支持多字節分隔符

最近項目中需要使用sqoop實現oracle與hdfs的數據交換,從oracle數據表導入到hdfs集群,以及把hdfs數據導出到oracle數據表。客戶要求Hdfs文本文件中,字段分隔符必須是“|@|”。然而發現sqoop的—fields-terminated-by選項只能支持單字節分隔符,無法支持多字節分隔符,難以滿足要求。上網搜索了一下,並沒有太多公開資料能較好的解決這個問題。這篇文章(http://www.cnblogs.com/YFYkuner/p/3748495.html)是通過修改codegen生成的Java代碼,再編譯實現多字節分隔。不過這種辦法還不夠通用,並不能完全滿足我的需求。但通過這篇文章可以學習到,分隔符主要是在DelimiterSet這個類定義。所以,我打算修改sqoop的源代碼,使其支持多字節分隔。

使用sqoop1.4.6,下載地址:http://www.apache.org/dyn/closer.lua/sqoop/1.4.6

1.   Sqoop工作原理

Sqoop在進行導入導出任務時,都會先自動生成一個java文件,並編譯打成jar包,再提交到hadoop集群真正執行MapReduce任務。可以先閱讀sqoop自動生成的java文件,看看其中數據導入導出的接口,以及分隔符如何被使用。這樣可以有一個整體的印象。參考http://www.cnblogs.com/YFYkuner/p/3748495.html

2.   核心代碼修改

2.1.  分隔符DelimiterSet的修改

首先了解一下分隔符org.apache.sqoop.lib.DelimiterSet的定義。

第一個字段field就是 –fields-terminated-by 指定的字段分隔符。源文件中變量類型是char,只能支持單字節。因此,首先需要將其修改為String類型,以便支持多字節分隔。

同時,DelimiterSet類的成員變量fieldDelim也需要修改為String類型。

2.2.  從Oracle導入Hdfs的修改

Sqoop主要是使用org.apache.sqoop.orm.ClassWriter類來實現從Oralce導入數據到Hdfs的。ClassWriter通過generateClassForColumns函數自動生成對應的java代碼,這些被生成的代碼才是真正在hadoop集群上執行。

其中導出到hdfs文本文件這段代碼,具體是generateToString函數生成。

由於我們把DelimiterSet的fieldDelim字段類型從char改成了String,因此ClassWriter自動生成的java源碼,也需要對應的修改。所以,需要修改如下:

2.3.  從Hdfs導出到Oracle的修改

從Hdfs導出到Oracle數據表,主要改動在於對Hdfs文本記錄的解析,能夠識別多字節分隔符。文本解析是通過org.apache.sqoop.lib.RecordParser的parseRecord方法來實現的。

源碼是通過一個有限狀態機來解析文本。我這里用String的split方法做了個最簡單的處理來替換。

2.4.  解析--fields-terminated-by參數

sqoop通過命令行參數--fields-terminated-by設置分隔符。所以需要在org.apahe.sqoop.tool.BaseSqoopTool中設置Input和Output的分隔符,修改為字符串類型。修改如下:

2.5.  變更源碼文件一覽

由於修改了變量類型,以及相關函數參數,為了解決編譯錯誤,還需要修改一些其它java文件。所有被修改的java文件如下。

3.   編譯和打包

在ubuntu下使用ant編譯和打包。參考sqoop的README,我安裝的是jdk1.8.0_121和ant1.10.1。

== Compiling Sqoop

 

Compiling Sqoop requires the following tools:

 

* Apache ant (1.7.1)

* Java JDK 1.6

 

Additionally, building the documentation requires these tools:

 

* asciidoc

* make

* python 2.5+

* xmlto

* tar

* gzip

 

To compile Sqoop, run +ant package+. There will be a fully self-hosted build

provided in the +build/sqoop-(version)/+ directory.

執行ant package命令即可。

在build下得到構建產物。

 

BTW:這里我指定了hadoop版本是2.6.1,只要在build.xml中修改版本號即可。

 

4.   測試

從Oracle導入Hdfs:

sqoop import --connect jdbc:oracle:thin:@ip:port --username username --password password --target-dir /hdfs/cluster/sqoop/dir --table oracletable --fields-terminated-by \\\\\|@\\\\\|

 

從Hdfs導出Oracle:

sqoop export --connect jdbc:oracle:thin:@ip:port --username username --password password  --table oracletable --fields-terminated-by \\\\\|@\\\\\| --export-dir /hdfs/cluster/sqoop/dir

 

驗證發現hdfs文件中字段分隔符確實是“|@|”,測試通過。

 

最后拋出一個問題供思考:分隔符是“|@|”,但為什么測試命令中--fields-terminated-by 指定的卻是“\\\\\|@\\\\\|”呢?

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM