前言
前陣子,公司的hadoop從hadoop1.02升級到hadoop2.4.1,記錄下升級的步驟和遇到的問題,和大家分享,希望別人可以少走一些彎路
技術選型
當前使用版本:
apache hadoop 1.0.2
hive 0.10
升級目標版本
Apache hadoop 2.4.1
Hive 0.13
升級風險點
Hdfs的升級
Hadoop升級最主要是hdfs的升級,hdfs的升級是否成功,才是升級的關鍵,如果升級出現數據丟失,則其他升級就變的毫無意義。
解決方法:
1. 備份hdfs的namenode元數據,升級后,對比升級前后的文件信息。
2. 單台升級datanode,觀察升級前后的block數。
備注:文件數和block數不是完全一樣,hadoop1和hadoop2的計數方式不一樣,可能相差2%左右。
Yarn的升級
Yarn的升級,它相對hdfs的升級,升級壓力沒有那么大,但是由於以前hive使用mapred,而現在直接使用yarn,所以兼容問題,就比hdfs多不少,所幸我們的任務基本是使用hive,所以我們更多的是面臨hive0.13和hive0.10的兼容問題。
而我們升級過程中,yarn的兼容問題,主要是資源的錯誤配置,兼容問題不多,而hive的升級,遇到更多的兼容問題,所以升級過程中,更多要測試的是hive升級導致的問題。
hdfs升級步驟
1.下載hadoop2.4.1,${HADOOP_HOMOE}/etc/hadoop/hdfs-site.xml中dfs.namenode.name.dir和dfs.datanode.data.dir屬性的值分別指向Hadoop1.x的${HADOOP_HOME}/conf/hdfs-site.xml中dfs.name.dir和dfs.data.dir的值。
2.升級namenode:/usr/local/hadoop 2.4.1/sbin/hadoop-daemon.sh start namenode –upgrade
3.升級datanode:/usr/local/hadoop 2.4.1/sbin/hadoop-daemon.sh start datanode
升級hdfs花費的時間不長,就是和啟動集群的時間要多2-3倍的時間,升級丟失數據的風險幾乎沒有。具體可以參考代碼:
namenode升級: org.apache.hadoop.hdfs.server.namenode.FSImage.doUpgrade(如果想查看你的apache hadoop版本是否可以升級到hadoop2.4.1,可以在這里查閱代碼判斷,apache hadoop 0.20 以上的都可以升級到apache hadoop 2.4.1)
datanode升級: org.apache.hadoop.hdfs.server.datanode.DataStorage.doUpgrade
org.apache.hadoop.hdfs.server.datanode.BlockSender
如果升級失敗,可以隨時回滾,回滾,數據會回滾到升級前那一刻的數據,升級后的數據修改,全部失效,回滾啟動步驟如下:
1. 啟動namenode: /usr/local/hadoop1.0.2/bin/hadoop-daemon.sh start namenode –rollback
2. 啟動datanode: /usr/local/hadoop1.0.2/bin/hadoop-daemon.sh start datanode –rollback
hdfs升級遇到的問題
1.datanode block數過多,導致啟動的時候做block report時,由於rpc調用的字節數限制,導致block report失敗。
解決方法是修改core-site.xml加入ipc.maximum.data.length屬性,值設置為幾百兆,根據具體情況調整。
2.同時啟動一百多台datanode時,namenode會卡死,這個問題,應該是hadoop的bug。
解決方法是,寫腳本,一台台啟動datanode。
3.Namenode Full GC過多,每次GC,系統停頓3-4分鍾
由於namenode保存元數據在內存,所以對老生代的壓力比較大,每次full gc時,系統就會卡死幾分鍾,解決方法如下:
(1). 使用cms gc算法
(2). 修改新生代和老生代比例為1:2,如果是1:4,會造成大對象在做ygc時,大對象直接進入老生代,造成老生代內存快速增長,full gc更加頻繁。
4.Namenode checkpoint超時
使用jdk1.6,在snn做checkpoin時,會超時,導致出錯,但是換jdk1.7,不超時,不出錯。
問題定位到snn請求namenode的jetty服務器的servlet時,文件傳輸完畢,但是NameNode的jetty沒有關閉連接,導致snn這邊讀數據超時退出。
最后的解決方式,是在snn的讀取數據的超時時間,從默認的1分鍾修改為20分鍾,NameNode的jetty會自動關閉連接,snn讀取數據可以正常退出,該方式並不是一個優雅的解決方式。
5.NameNode突然運行的很慢,每幾秒,rpc服務器就卡死10秒
由於在接口機啟動了一個DataNode,而注冊的時候,NameNode無法獲取這個意外的DataNode的hostname,最致命的是,注冊的時候,NameNode的底層系統類,獲取了寫鎖,在寫鎖 后,做ip的反域名解析這種可能出現耗時10s的操作。
而DataNode的注冊加入了重試機制,即使出錯,也會不斷重試,導致NameNode的服務相當緩慢。
最后的解決方案是kill掉接口機的DataNode,但是該問題的根本原因是hdfs的bug,需要修復這塊代碼:
org.apache.hadoop.hdfs.server.namenode.NameNodeRpcServer.registerDatanode org.apache.hadoop.hdfs.server.blockmanagement.DatanodeManager.registerDatanode final String message = "hostname cannot be resolved (ip=" + ip + ", hostname=" + hostname + ")"; LOG.warn("Unresolved datanode registration: " + message);
如果懷疑是非法DataNode連接NameNode導致集群緩慢,可以查log,找關鍵字: Unresolved datanode registration
6.HDFS做balancer很慢,一天居然只能balancer 2TB數據,導致集群的機器的存儲,個別機器存儲100%,大部分機器存儲卻很空閑
balancer代碼被重寫,以很保守的方式做balancer,而且參數根本無法配置優化,只能改代碼。
修改org.apache.hadoop.hdfs.server.balancer.Balancer.blockMoveWaitTime從30s修改為1s,這個可以提升很大的balancer的速度,在我負責的生產環境一般一次迭代只需要5s完成,它卻等了30s再檢測,真是無力吐槽。
修改org.apache.hadoop.hdfs.server.balancer.Balancer.run(Collection<URI> namenodes, Parameters p, Configuration conf) ,注釋掉以下代碼
if (!done) { Thread.sleep(sleeptime); }
更多優化,請查閱org.apache.hadoop.hdfs.server.balancer.Balancer做優化。
優化后,一天也只能balancer 12TB-20TB左右,只是勉強滿足要求。
繼續優化,優化balancer的根本問題,提高balancer每次迭代中,datanode balancer的吞吐量,balancer過慢,是bug來的,請修改以下代碼
org.apache.hadoop.hdfs.server.balancer.Balancer.Source.dispatchBlocks
(!srcBlockList.isEmpty() || blocksToReceive>0)) { PendingBlockMove pendingBlock = chooseNextBlockToMove(); if (pendingBlock != null) { + noPendingBlockIteration=0;//添加這行代碼,resetnoPendingBlockIteration,修復bug // move the block pendingBlock.scheduleBlockMove(); continue;
bug參考 https://issues.apache.org/jira/browse/HDFS-6621
還有final private static long MAX_BLOCKS_SIZE_TO_FETCH從2GB修改為300MB(重要,patch沒有這個參數,但是不加,依然無法提高吞吐量)
優化后,balancer的吞吐量可以達到一天64TB。
7.高可用環境,standby namenode會間歇性卡死,而hdfs客戶端偶爾會連接standby namenode,導致hdfs服務偶爾緩慢,經過排查,確定standby namenode每一分鍾會做editlog的合並,合並的時候,會鎖死FSNamenodeSystem的所有服務,導致standby namenode會間歇性出現3s的卡死,甚至10s的卡死。
代碼問題在org.apache.hadoop.hdfs.server.namenode.ha.EditLogTailer.doTailEdits
bug修復參考 https://issues.apache.org/jira/browse/HDFS-6763
yarn升級步驟
由於任務計算都是使用hive,所以yarn的升級很簡單,只是啟動yarn就行了。唯一要注意的是,從mapreduce升級到yarn,資源分配方式變化了,所以要根據自己的生產環境修改相關的資源配置,yarn的兼容問題,遇到的很少。
反而在任務計算中遇到更多問題的是hive,hive從0.10升級到hive0.13,語法更加苛刻,嚴格,所以升級前,盡可能測試hive的兼容性,hive0.13可以運行在hadoop1.02,所以升級到hadoop2之前,先升級hive到hive0.13以上,遇到問題,也沒什么好辦法,就是改hive sql,改hive參數。
1yarn任務無故緩慢,經常一個簡單任務本來需要30秒,經常會出現5分鍾都無法跑成功。經過跟蹤,發現是nodemanager啟動container時,初始化container(下載jar包,下載job描述文件)代碼是同步,修改代碼,把初始化container的操作修改為並發,解決該問題。
代碼問題在 org.apache.hadoop.yarn.server.nodemanager.DefaultContainerExecutor.startLocalize(該方法是synchronized)
bug修改參考 https://issues.apache.org/jira/browse/YARN-2730