sqoop導出數據到Oracle,數據重復


背景

由於我們公司使用了biee給業務方同學查詢數據,很多時候需要在hive計算結果后,導入到oracle中。但是在數據量特別大的時候,經常會出現:

Caused by: java.io.IOException: java.sql.SQLException: 關閉的連接
查看MR日志,可以發現其中有一段Connection Reset,然后sqoop任務就會重試,可以從日志中看到,重試並不是無縫的,那么就必然會導致一部分數據double(猜想重試應該是task級別的,也就是這個map task失敗后,重試整個map task,但是這個map的部分數據已經寫入了數據庫,猜想sqoop導出其實就是一堆insert into value,因為你可以發現任務在跑的時候,數據庫中表的數據是慢慢增加的)。

問題追蹤

sqoop導出任務可以配置update-key,但是部分表缺乏主鍵。或者加入這個字段會影響效率。在經過查詢后,發現一個非常好的解釋:http://stackoverflow.com/questions/2327220/oracle-jdbc-intermittent-connection-issue/,大致可以這么理解Oracle JDBC在和Oracle server連接時,是通過一種安全的方式。驅動使用的是java.security.SecureRandom

      SecureRandom random = new SecureRandom();
      byte bytes[] = new byte[20];
      random.nextBytes(bytes);

  調用者也可以調用generateseed方法來獲取一個

byte seed[] = random.generateSeed(20);

  同時,這里面有一條備注:

  Note: Depending on the implementation, the generateSeed and nextBytes methods may block as entropy is being gathered, for example, if they need to read from /dev/random on various unix-like operating systems.

  在Oracle JDBC中,就是通過獲取entropy來安全的連接。

  Entropy(熵)是由需要隨機數或者密碼學的操作系統或者應用程序收集/生成的隨機性。這種隨機性可以通過硬件來源,或者其他硬件噪音,多媒體數據,鼠標移動或者特定的提供隨機性的生成器。內核收集entropy並將他們存儲在一個entropy pool中。並使這部分隨機字節數據可以被操作系統或者應用訪問,通過特定的文件/dev/random 和/dev/urandom

  從/dev/random讀取以所請求的位/字節數量,排出熵池。從而提供密碼操作中需要的高度隨機性。在entropy pool 完全耗盡,並且沒有足夠的熵可用的情況下。會對/dev/random的讀操作阻塞,直到收集到額外的熵。因此,從/dev/random讀取的應用程序可能會阻塞一段隨機時間。

  相反的是,從/dev/urandom讀取不會阻塞。從/dev/urandom讀取也需要熵池,但是當缺乏足夠的熵時,它不會阻塞,而是重新使用來自部分隨機數據的位。據說容易受到密碼分析攻擊,因此不鼓勵從/dev/urandom讀取加密操作中需要的隨機性。

  java.security.SecureRandom類默認從/dev/random文件讀取,因此有時會阻塞隨機時間段。現在,如果讀取操作沒有返回所需的時間量,Oracle服務器會超時客戶端(JDBC driver),並關閉末尾的套接字來刪除通信。客戶端(JDBC Driver)從阻塞調用返回嘗試恢復通信會遇到IO異常。

解決方法

  在如果從/dev/random讀取阻塞,我們就讓它從/dev/urandom讀取,即加入參數sqoop export -D mapred.child.java.opts="\-Djava.security.egd=/dev/urandom"

  

  

  

 

 


免責聲明!

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



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