首頁>技術>

本文是房孝敬老師主題為“yarn在快手應用實踐與技術演進之路”的分享整理,內容包含yarn系統在快手的應用實踐,遇到的問題以及相應的技術演進過程。

講師介紹:房孝敬,快手大資料架構團隊排程方向負責人,目前負責快手公司Hadoop生態中排程、AI架構等子系統核心與周邊子系統的研發,並推動在公司內的應用。

2011年畢業於北京郵電大學,曾就職於阿里、騰訊。主要研究領域包括Docker雲平臺,分散式排程和計算平臺,AI架構等。

本文主要分為三部分:yarn的背景、yarn技術改進、yarn未來規劃。

yarn的背景

yarn大家都比較熟悉了,是從Hadoop1.0分離到2.0的比較重要的特性,把原來的jobtracker集中式排程變成yarn的二級排程,解決叢集擴充套件性的問題。yarn主要是分成了三個模組,ResourceManager來管理整個叢集的資源,NodeManager管理整個機器資源情況,ApplicationMaster管理整個APP的資源資訊。MR/SPARK/Flink實現了自己的AM邏輯在yarn上執行。

接下來介紹一下yarn的RM模組。yarn的RM模組按照功能可以分成兩部分:叢集狀態管理和資源分配。RM內部通過ResourceTrackerService和ApplicationMasterService 負責NM和APP的通訊互動。服務內部會生成相應的事件交給內部的事件處理器處理。驅動NM和APP狀態機的執行,確保APP和NM處於合適的狀態。排程通俗的講就是把節點的空閒資源分配給需要的APP。社群早期版本的yarn是在心跳邏輯裡面觸發整個排程邏輯的,這裡面有一個問題,排程過程會跟整個事件處理的競爭資源,導致兩方相互影響,效能不高,後來yarn社群做了優化,把整個排程邏輯拆離,放到單獨執行緒來做。

yarn在快手的應用特點

yarn在快手是非常典型的大資料的應用棧,yarn上面服務了一些經典的離線計算,像HiveSQL,最終會變成一個MR/SPARK作業或者PESTO查詢在yarn上執行。對於流式的實時資料處理需求,我們上層有一個青藤平臺來託管FLINK在YARN上執行。對於模型訓練的場景,我們是用XLearning作為排程器,排程TensorFlow,XGBoost,MPI等訓練學習引擎。基於Spark和XLearning,我們打造了亞瑟機器學習平臺,可以把資料處理流程和一些模型的訓練、預測流程做一個打通,方便使用者使用。

yarn技術改進

1.yarn技術實踐和演進

對yarn的一些改動,主要分成四個方面:(1)叢集穩定性方面的優化。(2)對yarn的搶佔機制做了優化。(3)yarn的排程效能提升。(4)計算叢集小IO優化。

2.整個叢集變大以後,對yarn排程系統來說面臨什麼問題?

直觀的感覺來說,整個叢集變大,節點就變多了,running 的 APP 也會增多。節點和APP增多會導致RM對外服務壓力變大,事件處理邏輯增多,事件處理壓力會比較大,並且對增加整個排程的壓力。因為你有很多的APP需要請求資源,你整個資源池又非常大,所以整個排程壓力是非常大的,怎麼解決這個壓力的問題。還有整個狀態變化會非常多,這時候會有一些事件處理,在yarn原生的框架裡面,事件處理是單執行緒的,會有各種各樣的問題,整個事件處理壓力非常大。針對這些問題我們做了一些針對性的優化。在大叢集裡面,機器故障會變得越來越頻繁,怎麼應對機器故障對整個作業穩定性造成的影響,這也是比較重要的方面。

3.在RM方面做的一些優化

從幾個比較經典的Case來說一下。有一次我們升級整個叢集的時候,導致整個叢集掛掉,一次升級幾百個機器,直接導致RM事件雪崩,最終OOM掉。我們發現是RM和NM互動有一些冗餘事件的,我們對冗餘事件進行了一些優化。對於NM,我們設計了一個慢啟動的策略,如果NM剛啟動沒有必要維持每秒彙報一次,開始可以20秒彙報一次,下次10秒,下次5秒,最終恢復到正常,這樣會把整個RM的事件處理壓力降下來,最終升級叢集對RM基本沒什麼影響。最終升級瓶頸變成了我們的運維繫統,不能併發升級太多機器。

HDFS是yarn非常底層的基礎設施,ResourceManager事件處理邏輯中有一些HDFS操作,HDFS卡一下,會造成整個事件處理邏輯卡住,最終整個叢集卡住。分析發現RM對HDFS的操作主要集中在失敗APP的處理,不是非常核心的邏輯,解決方案也比較簡單粗暴,把HDFS的操作從同步改成非同步。我們還對整個yarn事件處理邏輯進行排查,發現有一些像DNS的操作,在某些情況下也會比較卡,我們就把這種比較重IO的操作進行相應的優化,確保事件處理邏輯中都是快速的CPU操作,保證事件處理的高效和穩定。

經過優化之後,我們發現在叢集規模比較大的時候,事件處理過程還是要消耗非常多的CPU,我們profile發現,大部分的CPU的消耗是處理NM節點資訊的彙報,RM事件處理主要分幾個部分,有一些是節點級別的,有一些是APP級別的,有一些排程級別的。NM級別跟其他的是沒有太必要放在同一個執行緒處理,我們把它抽離出來,放在一個額外的執行緒上,這樣把大部分處理遷出去了,讓整個事件處理邏輯變得比較輕量。

2.6之後yarn支援狀態恢復,RM重啟理論上對APP是沒有影響的,可以把APP恢復出來,但是還是有一些比較小的缺陷,會造成APP的失敗,比如沒有把一些異常cover住,拋到AM,導致AM掛掉,token恢復在一些場景下也有問題。我們的RM升級是非常頻繁的,基本上2天左右就會升級新版本,叢集上有一些非常重要的作業,所以失敗,對他們造成的影響會比較大。

4.在從節點上面怎麼避免單點問題

yarn社群本身是有一個磁碟的故障監測機制的,基本的思路也會定期在磁碟上建立目錄,如果能建立成功說明這個磁碟是OK的,如果失敗就認為你這個磁碟有問題,這個比較簡單有效。但是在某些特定場景下,會有一些奇怪的磁碟問題,比如整個磁碟是好的,但是某個目錄是壞的,可能會導致某些特定的作業失敗。我們擴充套件了NM磁碟的黑名單功能,通過container的失敗資訊做一些規則匹配,這樣可以定向發現一些磁碟問題,把疑似有問題的磁碟放在黑名單裡面,不再向這個磁碟排程作業。

yarn有一個比較大的問題,如果你有一臺機器有問題,造成一些container排程失敗,並且系統沒有捕獲的話,會造成雪崩效應,比如一批container啟動失敗了,這臺機器資源看起來非常空閒,然後RM發現機器空閒,就調動更多container上來,然後越來越多的container失敗,最後導致很多APP執行失敗。社群提出了AM的黑名單機制,主要來解決AM的失敗問題,如果AM大量失敗,不往這臺機器上排程AM,APP內部依賴自己的黑名單機制,發現這些問題機器。我們覺得這樣可能會造成很多無效的container失敗,所以我們的解決思路是建立整個叢集的黑名單,而不單獨是AM的黑名單。當我們通過一些規則發現有大量的container在某一臺機器失敗,或者這臺機器的container排程速度非常異常,我們會把這臺機器放到我們叢集的黑名單裡面,不再向這臺機器排程資源。

資源隔離方面,現在社群主要是用cgroup做一些記憶體和CPU的隔離,其他方面的隔離非常弱的,我們當時碰到一些場景比如磁碟打滿了,FD洩露、執行緒洩露的問題。曾經在上一家公司的時候寫過一個程式,有執行緒洩露的問題,洩露之後把整個機器的執行緒全用光了,這樣導致這個機器所有服務異常,計算框架計算不斷把這個問題task排程到其他機器上,最終把整個叢集都打掛了。解決方案就是對container的執行緒數目,磁碟大小定期檢查,如果超過闕值,直接kill掉。

單臺機器的故障率比較低,但叢集規模變大之後,整體故障率變得非常高。怎麼發現這些機器是個問題。我們藉助container失敗率做一個基本的判斷。如果是一臺機器失敗率高於正常值,可能是非常有問題的,需要人工檢查一下。還可以藉助一些物理指標的異常檢測,因為在離線系統裡面,CPU打得比較高的,load也比較高,所以當前這些指標可能不容易發現,用syscpu作為異常檢測指標,叢集中經常有些機器task跑的比較慢,重啟機器就好了。一臺機器有問題會導致Task失敗,Task失敗會導致作業的失敗,我們做了一個失敗APP的歸因系統,可以從歸因系統裡面發現一些問題機器。單純從作業失敗還不夠,我們正在做一個基於失敗TASK的歸因系統,因為TASK有容災重試機制,可能會掩蓋潛在問題。

5.yarn排程方面做的優化

yarn一個主要的功能,就是要排程整個叢集的資源,它的視角是整個叢集的節點資訊,還有APP的資源請求資訊,還有一些佇列資訊。yarn的排程模型裡面,邏輯是比較複雜的, 簡單說,先來一個節點,如果這個節點有一定資源的話,會對叢集中的一級佇列做排序,然後選出最應該排程的佇列。選擇這個佇列之後找這個佇列下面的二級佇列進行排序,逐漸遞迴找到APP,選一個合適的APP進行排程,如果資源排程不上,再找下一個APP。排程邏輯是要耗費很大資源的,主要是各種排序。但整個排序真的有這麼大必要嗎?

我們早期思路就是怎麼減少整個排序的時間,減少排序時間從三方面著手,減少排序規模,減少單次排序時間,優化排序演算法。如何減少排序規模?叢集裡有幾千個佇列,幾千個佇列是不是都需要資源?APP是不是都需要資源,是否都需要排序?實際場景中大部分是不需要資源和參與排序的,這樣把整個排序規模減小了。在排程單詞排序時,使用了java collection.sort()函式排序的,每次排序涉及到兩個元素的compare,怎麼來減少compare的開銷?在yarn裡面每一次compare的時候有很多可以可以優化的地方,比如計算一個佇列使用的資源量,有一些臨時物件可以cache住,最終縮小整個單次排序的時間。Collection.sort底層使用歸併排序,我們改成堆排序,經過這些優化後,差不多能夠支撐5000臺機器的規模。

優化之後還是存在一個很明顯的問題,排程的擴充套件性是不足的,因為整個排序過程都是在一個CPU裡面,如果想利用更多CPU,會涉及到整個排序怎麼切分,節點怎麼切分、作業怎麼切分,怎麼讓資源分配達到均衡,怎麼保證公平性,涉及到非常複雜的策略,非常難拆分。yarn排程是先選一個節點,然後再選APP,排程過程只看到一個節點的資訊,而看不到整體的叢集資訊,整個排程策略是非常受限,很難加一些策略在裡面。比如yarn本地化一個非常簡單的功能實現上比較複雜,在整個排程框架層面。如何來解決這個問題?

最終決定我們重寫排程邏輯,開發了Kwaischeduler。我們覺得在整個叢集裡面有一個上帝視角的,你可以拿到整個叢集的資源使用情況和資源配置情況和每一個佇列、每個APP的資源需求量和資源的配置。基於這些資訊,我們能夠計算出來,應該給每一個APP來分配多少資源。然後App資源的分配過程我們完全可以併發起來,藉助多執行緒的能力,去整個資源池裡面搶這些資源。因為我們是先排程APP的,所以搶這些資源的時候,借鑑K8S的排程思路,先對節點進行過濾,然後按照不同的排程策略,給每個節點打分,每個策略可以有一個權重,從理論上來說每個APP都可以有自己的策略。Kwai scheduler上線後排程效能和排程策略擴充套件性不是問題,現在單叢集的排程效能可以達到每秒鐘4萬多container,對比國內其他廠商和社群,我們的排程效能和擴充套件性上表現還不錯。

簡單介紹一下底層實現。首先主要分成兩部分,一部分是叢集資源的預分配過程,把一些資源分配到每個APP,第二部分是APP怎麼去每臺機器上競爭資源。有一個單獨執行緒定期會對叢集情況做snapshot,基於snapshot來做一個上帝視角的資源分配。我們為每個APP分配出資源之後,就可以把APP丟到執行緒池裡面併發搶資源,對相應的節點排序,選出分數最高的節點,最終你會有一個commit的過程,真正拿到資源。整個排程分配結束後,會把整個分配結果寫回到整個原生的yarn框架。

在計算叢集裡面有一個大的問題,就很多的小IO。在我們業務場景裡面,快手的資料規模比較大比較大,經常是幾十萬個map,幾千reduce。一個map也沒有多少資料,可能就是250M,reduce單次shuffle取的資料非常小的,可能只有幾K幾十K,所以有很多的小IO,導致整個叢集磁碟util非常高,但是磁碟讀寫速度非常慢。針對這個問題,我們對MR的shuffle過程做一個Cache。在shuffle過程中,當一個請求來的時候,我們分析一下這次shuffle過程有沒有可能產生比較多小IO,可以按需把shuffle資料放到cache裡,只需要一次大的IO把資料搬到Cache裡面,後面的shuffle請求可以直接從cache裡面讀,消滅了後面多次小IO,通過這個我們優化,提升了整個的叢集IO效能。

yarn為什麼有搶佔的問題,為什麼K8S這些線上系統不會有搶佔問題。yarn主要是離線排程系統,資源使用不像線上系統比較恆定,有一些突增,這意味著如果完全資源配額限制資源,會導致整個叢集的資源利用率降低或者job的執行時間拉長。所以yarn允許你的資源使用超過配額。這帶來另一個問題,使用超過配額後,當另一個佇列需要資源的時候,能不能及時把這些資源釋放出來。在大部分情況下是可以的,因為離線系統的作業一般會比較快的結束。但是在特殊場景下,有可能是一個spark作業一直佔著資源不釋放,可能會導致一些比較核心的作業拿不到資源。搶佔主要是解決這個問題。但是在大部分的公司,搶佔是沒有開啟的,原因主要因為社群版本的搶佔不太可控。會基於佇列的資源使用量來決定是否搶佔,如果核心佇列資源使用超過配額太多, 可能會被非核心佇列搶佔,存在比較大的風險。我們解讀這個問題的思路是基於一些核心佇列來觸發的搶佔,搶佔只能從核心的佇列觸發,被搶佔的只是非核心佇列,這樣就解決低優先順序作業搶佔核心的作業問題。但是這個方案還是有些問題,如果使用資源超過配額的都是一些核心的作業,這時候怎麼處理?我們主要思路是,希望構建整個叢集的作業優先順序體系,把作業重要性系統做一個全域性拉起,這樣我們可以做一些佇列內部的搶佔和跨核心佇列之間的搶佔。

yarn的未來規劃

構建作業分級保障,現在我們yarn的叢集規模比較大,大家使用的資源都非常多,但是這些資源有沒有用到真正比較重要的業務上,其實我們是有些疑問的,有多少無效的計算在裡面,當然這個涉及到業務層的優化。為作業打一些作業的標籤,基於這些任務的標籤,以及優先順序的特性,刻劃整個叢集資源的使用情況,為預算或者其他的技術方案提供一些技術的底層支援。

我們現在單個yarn叢集規模在國內是top級的,但是單叢集畢竟是容量有限,我們後面會考慮多叢集建設的方案,社群的federation方案在跨IDC方面有些問題,如何在業務透明的前提下,建設跨IDC叢集有非常多問題需要解決。

yarn現在主要託管的是一些離線計算的資源,公司還有很多空閒資源沒有使用,怎麼來使用這些空閒資源,怎麼做到把一些合適的任務調入到一些比較空閒的機器上,當這個機器需要的時候,及時把任務遷移走,怎麼減少業務相互的影響,底層這方面需要做什麼支撐,這都需要探索。

最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 高階Linux運維工程師養成記-Unix/Linux起源和哲學思想