Search

記一次上千節點Hadoop集群升級過程-科技新聞 - 臺灣新浪網

原標題:記一次上千節點Hadoop集群升級過程

繼《記一次超萬億規模的Hadoop NameNode性能故障排查過程》之後,雖然解決了Hadoop2.6.0版本在項目中的問題,但客戶依然比較擔心,一是擔心版本過老,還存在其他未發現的問題;二是按目前每天近千億條的數據增長,終究會遇到NameNode的第二次瓶頸。基於上述原因,我們決定將當前集群由Hadoop2.6.0版本升級到Hadoop3.2.1版本,且啟用聯邦模式。

歷時2周,我們將錄信資料庫LSQL的源碼進行了修改,適配Hadoop聯邦機制,以期達到擴容至上萬節點的能力。

因為是數十億數據規模的生產系統,無論是丟數據還是長時間停服務都是不可接受的,所以客戶方和錄信側都非常慎重,做了大量的前期準備,進行了多次升級演練,包括各種情況的回退方案、數據丟失的挽回方案、升級后的功能性能驗證,大大小小做了十幾次測試。但即使做了充分的準備,我們還是遇到了幾個預想不到的問題。

永不退縮是錄信最深的執著,經過一周的日夜奮戰,集群終於成功升級到社區最新Hadoop3.2.1版本,啟動3個聯邦,徹底解決NameNode負載問題。

記錄下升級中遇到的問題,分享給大家,希望能有一點小小的貢獻,讓大家越過錄信趟過的雷!

一、 跨多個聯邦后,速度沒有變快,反而變慢

理論上,升級成跨聯邦機制,讀寫請求會分別均衡到三個不同的NameNode上,降低NameNode負載,提升讀寫性能,然而事實是NameNode負載不但沒有降低,相反變得非常非常慢。

集群卡頓的程度,對於生產系統來說是不可用的,升級已經進行了三天了,再不解決就要立即啟動回退方案。心有不甘,連夜奮戰。

抓了堆棧,知道主要問題還是NameNode卡頓,生產系統已經不能繼續調查下去了,不想回退,就得讓系統可用,那就得從我們最熟悉的地方下手---修改錄信資料庫LSQL,給所有請求NameNode文件的地方加上緩存,只要請求過的文件,就緩存下來,避免二次請求NameNode。

LSQL修改後NameNode狀態有非常大的改善,系統基本可用。但具體為何升級到聯邦后NameNode的吞吐量不升反降,我們沒能給出合理的解釋,只能考慮為歷史數據還在一個聯邦上,不均衡,之後隨著新數據的逐步均衡,會有所好轉,但這並不准確可靠。

二、 升級聯邦后LSQL不穩定總掛掉

升級后,幾乎每隔幾天LSQL就會掛掉一次。

觀察錄信資料庫LSQL的宕機日誌,發現有大量的如下輸出,證明Hadoop NameNode經常位於standby模式,導致Hadoop服務整體不可用,從而引起錄信LSQL資料庫宕機。

進一步分析NameNode發現Hadoop的NameNode並未宕機,active與standby都活著。結合Zookeeper日誌分析發現,期間發生了NameNode的activer與standby的切換。

這裏涉及兩個問題,一是為什麼發生了主備切換,二是切換過程中是否會導致服務不可用。

針對主備切換的原因,經過對比切換髮生的時間,發現切換時NameNode做了比較大的負載請求,如刪除快照,或者業務進行了一些負載較大的查詢。這很有可能是因為NameNode負載較高,導致的Zookeeper鏈接超時。具體為什麼NameNode負載很高,這個我們在後面闡述。

至於切換過程中是否會導致服務不可用,我們做了測試。第一次測試,直接通過Hadoop 提供的切換命令切換,結果切換對服務沒有影響。第二次測試,直接將其中的Active NameNode給kill掉,問題復現了。可見在Hadoop 3.2.1版本里,active 與standby的切換,在切換過程中,是存在服務不可用的問題的。我們針對報錯位置進一步分析如下:

看RouterRpcClient類的設計實現,應該是存在failover的邏輯。相關配置參數key值如下。

最終分析RouterRpcClient.java這個類,發現其設計邏輯是有問題的,雖然預留了上面那些參數,但沒有生效,NameNode在主備切換過程中,存在兩個NameNode同時處於Standby的過程。並且這個階段,會直接拋錯,導致因報錯而服務不可用。

我們詳細閱讀了該類的實現,發現該類雖然預留了重試的邏輯,但是這些重試的邏輯並沒生效,存在BUG,故我們對此進行了修復。修復后錄信資料庫LSQL的宕機問題不再出現,如下是涉及源碼的分析過程:

如下是修復版本后,router重試過程中記錄的日誌:

  三、 錄信資料庫LSQL查詢的時候間歇性卡頓

Hadoop升級到3.2.1版本后,錄信資料庫LSQL會出現間歇性的卡頓情形,導致業務查詢頁面總是在「轉圈圈」。

到現場后第二天遇到了該現象,經過了一系列的排查和追蹤,最終定位在Hadoop 的NameNode卡頓。具體體現在進行一次ls操作,會卡頓20~30秒的時間。進入NameNode節點的機器觀察負載情況,發現CPU的負載佔用在3000%上下。

后經過多次抓取jstack,發現導致NameNode卡頓的堆棧的位置點如下:

沒錯,是addBlock,也就是寫數據的寫鎖會阻塞所有的查詢。按照以往的經驗,我們認為是上圖中的鎖引起的,故我們進行了去鎖操作。

由於NameNode主備切換的問題已經解決,所以我們可以在生產系統通過熱切的方式來驗證我們的問題。去鎖后的結果非常遺憾,卡頓現象不但沒有減少,相反變得更嚴重,整台NameNode的負載不但沒有降低,反而直接飆升到全滿。

沒辦法,我們只好繼續排查原因,仔細分析該類的相關實現,最終發現如下問題:

結合上面的原因,我們稍微改了下代碼實現。

經分析發現進行一次addBlock的請求,這裏就有一次循環,這是一個機架上的所有機器。這意味著每調用一次addBlock方法,NameNode就要對一個機架內的設備進行一次循環,集群設備上千台,就是循環上千次,那這CPU使用率還了得!之前加鎖狀態,因為有鎖的限制,只是會導致寫入慢,查詢還算可用。現在把鎖去掉了,乾脆CPU飈滿,更是查不動了。然後jstack發現卡頓的地方變了,如下圖所示:

我們臨時調整NameNode的日誌級別,調整為DEBUG級別,看到了如下的輸出,更是進一步的驗證了我們的想法。

同時我們對比了下Hadoop2.8.5版本的源碼,發現這個地方的邏輯在Hadoop3.2.1中做了較大的變更。存在設計不當的問題,這種循環方式會耗費很多CPU。設計的本意是隨機抽取節點,卻要遍歷一個機架下的所有節點,挨個加一遍鎖。為了一次addBlock,平白無故加了幾百次鎖,哪能這樣設計呢?我們仿照2.8.5的一些寫法,重新修正了一下,針對這裏的隨機方式進行了重新改造。

改動完畢后,再繼續抓jstack,崩潰的是,這塊的邏輯確實抓不到了,但又在別的地方出現了,一樣有個類似的循環。詳細看代碼發現Hadoop3.2.1的這個類裏面,這樣的循環太多了,在生產系統上改不起,也不敢改了。只能轉變思路來解決,如果是因為這個循環的問題導致的NameNode卡頓,為何不是一直卡頓,而是間歇性卡頓,理清楚這個思路,也許就打開了一扇窗。

1. SSD機器的Xreceiver引發的血案

我們分析了循環里的IP列表(DataNode的IP),並且結合現場日誌的設備,發現了一個規律,這些循環裏面的IP,均是SSD設備的IP,並非是SATA設備的IP。現場設備分為六組,每組一個機架,SATA和SSD各佔一半。從IP的規律上來看,這些IP均是SSD設備。進一步分析,什麼情況下這些DN會被加入到這個循環裏面,從日誌和源碼分析,我們最終定位在Exclude上,也就是說Hadoop認為這些設備是壞了的,是應該被排除掉的設備。

難道是我們的SSD設備全都宕機了,或者他們的網路有問題?但經過排查,我們排除了這些問題。問題又回歸到了源碼層面,經過了大約1天的追蹤定位,發現如下邏輯:

Hadoop在選擇寫入的DN的時候,會考慮到DN的負載情況,如果DN負載比較高,它會將這個節點加入到Execude裏面,排除掉這個節點。而判斷一個DN負載高低的就是Xreceiver的鏈接數量。默認情況下,只要Xreceiver的鏈接數量超過了整個集群連接數量的2倍,就會排除掉這個節點。而LSQL本身採用了異構的特性,意味著我們會優先從SSD盤讀取數據,而SSD盤設備的性能好,數量又相對較少,導致這些SSD設備的機器連接數遠高於SATA盤的鏈接數。SATA盤冷數據偏多,幾乎很少有人去查詢。針對這一情況,就會出現在一瞬間,因為連接數的問題,導致所有的或大多數的SSD設備被排除掉的情形。

我們的Hadoop集群有一部分數據的寫入是採用ONE_SSD的模式,也就是一份數據存儲在SATA設備上,另一份數據會存儲在SSD設備上。而Hadoop3.2.1的特性,會隨機在SSD設備里抽取一個節點,如果它沒有在排除的execlude列表裡,則會寫入到這個設備里。而如果該設備被排除了,那麼Hadoop就會再次嘗試,再隨機抽取其他節點,如此反覆循環。但是我們的SSD設備因為Xreceiver負載的關係,絕大多數或全部都被排除掉了,直接導致了不斷的循環,甚至上百次,最終還有可能發現一個SSD設備都不可用。日誌里會提示2個副本1個SATA的寫入成功了,還缺少一個副本沒寫成功,如下圖所示:

上述問題中,直接導致大數據集群的兩個致命性問題為:第一,NameNode CPU飈高,產生嚴重的間歇性卡頓;第二,SSD設備間歇性的被排除掉,只寫成功了一個SATA副本,如果SATA設備突然損壞一個盤,那麼數據就會丟失。

針對SSD的Xreceiver修復方法很簡單,禁用該功能,或者調大倍數,如下圖所示:

調整完畢后,我們非常明顯的感受到了NameNode負載的下降,同時業務的所有查詢,響應速度回歸正常。

2. 機架分配策略不合理導致的同樣問題

在我們驗證上述問題的過程中,雖然NameNode的負載明顯下降,但是上面所說的循環情況依然存在,查看DEBUG日誌,令我們非常驚訝的是,這次循環的設備不是SSD設備,變成了SATA設備,這是什麼情況?說不通啊。

還好,經過幾天時間研讀Hadoop源碼,初步了解了這部分邏輯,我們打開Hadoop的DEBUG日誌,觀察到如下日誌:

我們發現,一個機架下允許寫入的塊數超了,而別的機架沒有可用的存儲策略寫入時,就會出現上述的循環。我們看下,一個機架下允許寫入多少個數據塊,又是怎麼決定的?如下圖所示:

我們分了6個機架,3個SATA,3個SSD,從日誌看,我們一個數據塊要寫入24個副本,這24個副本均要寫入到SATA設備上。每個機架Rack上最多可以寫入5個副本,3個SATA機架可以寫入15個,另外的9個寫入失敗。Hadoop3.2.1在計算機架策略的時候並未考慮到這種情況,另外的SSD設備無法寫入SATA存儲策略的數據,導致了Hadoop在這種情況下將SATA設備循環幾百遍,CPU飆升。

由於後續的9個副本,一直沒有地方寫入,Hadoop就會又像之前那樣,將所有的SATA的設備循環上幾百遍。這也會導致CPU的飆升。

我們實際生產環境中,寫入24個副本的情況是極少的,只存在更新的一些場景,由於帶更新的數據,需要被每個節點讀取(有點類似Hadoop的DistirbuteCache),如果2副本,會造成個別DataNode的壓力過大,故我們增大了副本數。

這一情況也跟之前業務提出,只要一執行更新,就會明顯感受到業務查詢的卡頓的現象對應上。

針對這個問題,我們認為應該對機架分配策略進行調整,不允許單獨的SSD與SATA在各自不同的機架上,一個機架上必須即有SSD設備,也要有SATA設備。這樣這個問題就可以規避了。但我們擔心一旦更改了此時的機架策略,會造成Hadoop的副本大量遷移(為了滿足新的機架策略的需要),我們的集群規模太大了,我們最終還是選擇了修改NameNode的源碼。從源碼層面解決這個問題,如下圖所示:

四、 總結

1. Hadoop Router針對NameNode的failover沒有進行重試處理,在主備切換期間,服務報錯,整體不可用。

2. Hadoop addBlock 在3.2.1版本的設計思路上會因為機架策略的問題,進行循環處理,導致CPU佔用很高,加鎖頻率很高。

Let's block ads! (Why?)



"過程" - Google 新聞
July 24, 2020 at 10:06PM
https://ift.tt/3eTCZZX

記一次上千節點Hadoop集群升級過程-科技新聞 - 臺灣新浪網
"過程" - Google 新聞
https://ift.tt/2UsLxyQ
Shoes Man Tutorial
Pos News Update
Meme Update
Korean Entertainment News
Japan News Update

Bagikan Berita Ini

0 Response to "記一次上千節點Hadoop集群升級過程-科技新聞 - 臺灣新浪網"

Post a Comment

Powered by Blogger.