前言
這篇文章主要是用sqoop從mysql導入數據到hive時遇到的坑的總結。
環境:
- 系統:Centos 6.5
- Hadoop:Apache,2.7.3
- Mysql:5.1.73
- JDK:1.8
- Sqoop:1.4.7
Hadoop以偽分布式模式運行。
一、使用的導入命令
我主要是參考一篇文章去測試的,Sqoop: Import Data From MySQL to Hive。
參照里面的方法,在mysql建了表,填充了數據,然后按照自己的情況輸入了命令:
sqoop import --connect jdbc:mysql://localhost:3306/test --username root -P --split-by id --columns id,name --table customer --target-dir /user/cloudera/ingest/raw/customers --fields-terminated-by "," --hive-import --create-hive-table --hive-table sqoop_workspace.customers
然后開始了打地鼠之旅。
二、遇到的問題及解決
1. 用文本字段進行分區的問題
報錯信息:"Generating splits for a textual index column allowed only in case of "-Dorg.apache.sqoop.splitter.allow_text_splitter=true" property passed as a parameter"。
主要問題是“--split-by id”這個參數指定的id是一個文本格式,所以需要在命令中加入選項"-Dorg.apache.sqoop.splitter.allow_text_splitter=true",補齊命令:
sqoop import "-Dorg.apache.sqoop.splitter.allow_text_splitter=true" --connect jdbc:mysql://localhost:3306/test --username root -P --split-by id --columns id,name --table customer --target-dir hdfs://harry.com:9000/user/cloudera/ingest/raw/customers --fields-terminated-by "," --hive-import --create-hive-table --hive-table sqoop_workspace.customers
2. Hadoop歷史服務器Hadoop JobHistory沒開啟的問題
報錯信息:“ERROR tool.ImportTool: Import failed: java.io.IOException: java.net.ConnectException: Call From harry.com/192.168.0.210 to 0.0.0.0:10020 failed on connection exception: …”。
主要原因是sqoop在運行完MapReduce任務之后需要用hadoop jobhistory記錄這些作業信息並存放在指定的HDFS目錄下,默認情況下是沒有啟動的,需要配置完后手工啟動服務。
解決方法:mapred-site.xml添加如下配置:
<property> <name>mapreduce.jobhistory.address</name> <value>0.0.0.0:10020</value> </property> <property> <name>mapreduce.jobhistory.webapp.address</name> <value>0.0.0.0:19888</value> </property> <property> <name>mapreduce.jobhistory.done-dir</name> <value>/history/done</value> </property> <property> <name>mapreduce.jobhistory.intermediate-done-dir</name> <value>/history/done_intermediate</value> </property>
重啟hdfs和yarn:
stop-dfs.sh stop-yarn.sh start-dfs.sh start-yarn.sh
啟動歷史服務器:
$HADOOP_HOME/sbin/mr-jobhistory-daemon.sh start historyserver
后面如果需要停止,可以用命令:
$HADOOP_HOME/sbin/mr-jobhistory-daemon.sh stop historyserver
然后重新執行命令。
3. 連接元數據存儲數據庫報錯
報錯信息:“Caused by: javax.jdo.JDOFatalDataStoreException: Unable to open a test connection to the given database. JDBC url…”。
主要是因為我用的hive元數據數據庫是默認的Derby,我在另外一個會話開了一個hive cli來訪問hive,而Derby的一個缺點就是當有多個用戶同時訪問hive的時候,會報錯。
解決:退出hive cli,重新運行
4. 沒有在hive創建數據庫
報錯信息:“ERROR ql.Driver: FAILED: SemanticException [Error 10072]: Database does not exist: sqoop_workspace…”,這個就很明顯了,直接在hive里創建一個就是了。
5. 其他警告和報錯
其他報錯實際上沒有阻礙導入過程,譬如下面這個WARN:
“WARN hdfs.DFSClient: Caught exception java.lang.InterruptedException…”,實際上是hadoop自己的bug,具體是HDFS 9794的bug:
當關閉DFSStripedOutputStream的時候,如果在向data/parity塊刷回數據失敗的時候,streamer線程不會被關閉。同時在DFSOutputStream#closeImpl中也存在這個問題。DFSOutputStream#closeImpl總是會強制性地關閉線程,會引起InterruptedException。
這些報錯一般忽略就可以了。
三、一些補充
1. 為什么使用--split-by
在workflow上有個討論說得很明白:
--split-by : It is used to specify the column of the table used to generate splits for imports. This means that it specifies which column will be used to create the split while importing the data into your cluster. It can be used to enhance the import performance by achieving greater parallelism. Sqoop creates splits based on values in a particular column of the table which is specified by --split-by by the user through the import command. If it is not available, the primary key of the input table is used to create the splits.
--split-by is used to distribute the values from table across the mappers uniformly i.e. say u have 100 unique records(primary key) and if there are 4 mappers, --split-by (primary key column) will help to distribute you data-set evenly among the mappers.
實際上使用—split-by參數,是為了運行map任務的時候,能夠更好的分發數據。
四、參考
1. Sqoop Import: "-Dorg.apache.sqoop.splitter.allow_text_splitter=true"
3. Already tried 0 time(s); retry policy is RetryUpToMaximumCountWithFixedSleep解決方法
4. WARN hdfs.DFSClient: Caught exception java.lang.InterruptedException
(完)