雲梯的多NameNode和跨機房之路



2013年4月,阿里雲梯集羣所在的數據中心(IDC機房)的機位已滿,無法繼續擴充集羣。根據當時阿里集團數據量的增長趨勢,在可以預見的很短時間內,集羣規模將因爲機房機位不足而無法繼續擴充。由於當時雲梯的Hadoop版本還不支持單集羣跨機房分佈的功能,所以阿里集團的大數據業務 將因爲集羣規模的限制而停止發展。雲梯的跨機房項目就在這種背景下開始的。目標非常明確:構建一個支持跨機房的Hadoop集羣。

技術挑戰

要構建一個跨機房的Hadoop集羣,有非常多的技術難點。

難點1:NameNode的擴展性

衆所周知,Hadoop HDFS中的NameNode單點是阻礙Hadoop集羣能夠無限擴充的一個最大問題點。雲梯在跨機房之前一直是單NameNode的結構,不管如何優化,其服務能力有其上限。雖然經過雲梯開發團隊的多輪優化,已能超過5000臺規模(日平均RPC訪問量達到25億次),但考慮將規模擴大一倍的話,顯然 無法實現。所以雲梯的Hadoop版本要能支持多NameNode就非常必要。

難點2:機房間網絡限制

有些問題並不是將其中一個機房的所有Slave直接彙報給另外一個機房的Master就可以解決的,因爲機房間的帶寬是一個巨大的障礙。

難點3:數據應該如何跨機房分佈

切分成多NameNode以後,勢必需要對數據進行劃機房甚至是跨機房的分佈,分佈的策略需要從業務層面進行整體的規劃。這個問題的解決方案並不在本文討論範圍之內,所以只簡單提出一下。實際上,雲梯團隊是根據上層應用對數據的訪問分佈和需求情況聚類生成的數據分佈。

難點4:計算應該如何跨機房調度

數據跨機房分佈後,計算調度該如何進行最優的調度策略,以避免數據在機房間的來回拷貝以及作業跨機房讀取數據呢?

難點5:幾十PB數據的遷移,以及帶數據升級

帶着上百PB數據進行集羣整體升級,數據不能有任何丟失,是一個非常大的挑戰。

難點6:怎樣做到對用戶透明?

實現了多Master以後,如何對用戶透明,不需要雲梯上幾十萬個job做任何修改就能無縫兼容,是對開發團隊的另一個巨大挑戰。

難點7:方案是否能擴展到多機房(>=3)?

爲了以後進一步跨越更多的機房,雲梯版本需要考慮的不僅是雙機房分佈,而是多機房分佈。

解決方案的詳細步驟

明確了需求和難點,接下來就需要有明確的實施步驟,經過開發團隊、測試團隊、運維團隊和業務團隊的多方溝通和頭腦風暴,雲梯跨機房項目確定瞭如下的技術實施步驟(這裏的設計方案,是按照整個項目實際的實施步驟順序來介紹的,以方便大家理解每一步的初衷和解決的問題,會對每一步解決了什麼問題進行相應介紹)。

第一步,將雲梯集羣升級爲支持Federation版本(基於雲梯自身的版本進行開發),將現有NameNode作爲一個NameSpace,爲“NameNode1”,該“NameNode1”的NameSpace下擁有云梯的全量數據,規模爲5000臺。

第二步,在同機房中搭建另一個NameNode,爲“NameNode2”。該NameNode下的NameSpace爲空,剛開始不管理任何數據。同時在所有的DataNode上創建針對NameNode2的BlockPool,用來向NameNode2彙報。

第三步,將NameNode1中的部分數據(如50%)遷移到NameNode2(這裏的遷移包括NameSpace中的元數據遷移和底下DataNode磁盤中的block)。這一步完成之後,雲梯結構如圖1所示。這一步是一個非常大的難點。


圖1 雲梯多NameNode架構圖

可以看出,完成了這一步,基本上就解決了前述難點1(NameNode的擴展性問題)。到這一步結束,單點NameNode就變成了多個,原先由一個 NameNode來承擔的對文件系統所有元數據的訪問被分攤到了多個NameNode上,NameNode的性能、內存和擴展性問題都不復存在。

經歷完上述三步,實際上雲梯已經完成了多NameNode的切分,但數據仍然在一個機房裏面,分別由兩個NameNode來分別管理。此時將另一個機房(機 房B)已經準備就緒的Slave機器開始同時向兩個NameNode進行彙報。也就是說,將另一個機房的Slave機器進行上線服務。

第五 步,將NameNode2從原先的機房(機房A)轉移到另一個機房(機房B)。這樣,兩個NameNode從物理機房上就已經分離,只不過 NameNode2上管理的數據所對應的block塊仍然分佈在機房A,需要對這部分數據(圖1中的/group/B和/group/D的blocks) 進行遷移。這裏的遷移方式很特殊,雲梯團隊開發了一個新的Master節點,叫做CrossNode,來實現數據的跨機房分佈和跨機房拷貝的策略,將在後 面的內容中詳細介紹。

經過第五步以後,雲梯已經達到多NameNode切分,以及數據的NameSpace切分以及相應的block多機房 分佈。接下來的一個問題是:如何讓底層的這些變更對上層業務完全透明?我們採取的策略是ViewFS。簡單地說,ViewFS是雲梯開發團隊全新開發的一 個實現Client端對多NameNode的透明感知組件,讓客戶端能夠自動找到正確的NameNode來進行數據的讀寫。實現了ViewFS的的雲梯 Hadoop Client結構如圖2所示。


圖2 雲梯Client架構圖

經過客戶端的改造和升級,以前老的訪問方式由智能的Client接管。由Yunti3FileSystem根據訪問路徑自動選擇要訪問的NameNode,實現了數據的分切對客戶端透明。也由此解決了前述難點6(怎樣做到對用戶透明)。

到此爲止,雲梯的數據實現了跨機房分佈,NameSpace實現了跨機房切分,客戶端訪問也實現了對用戶透明。接下來就是計算調度跨機房的實現。由於MapReduce本身的特徵,計算調度很多情況下是跟着數據走的,所以要實現跨機房計算調度,雲梯採取的策略如圖3所示。


圖3 雲梯跨機房調度架構圖

從圖3可以看出,雲梯集羣分別在兩個機房各啓動了一個MapReduce,用來做實際任務的分配和調度,而job在提交到JobTracker之前,有一個新開發的JTProxy組件來對job的提交進行前提判斷。由於雲梯的計算資源是按照組來劃分的,所以JTProxy要根據計算組的配置來決定向哪個JobTracker進行job提交。並且JTProxy還提供了一個統一的Web界面供用戶查詢多個JobTracker上的作業運行情況。至此,前述難點4(計算應該如何跨機房調度)迎刃而解。

經過上述多個步驟,雲梯集羣就實現了多NameNode切分、數據的跨機房分佈和管理、計算的 跨機房調度等,雖然物理上雲梯集羣跨越兩個數據中心,但對上層業務來說,完全感知不到底層的變動。不僅如此,由於實現了多Master的切分,讓多個 NameNode來分擔以前一個NameNode來管理的所有數據,所以也很大程度上釋放了以前單NameNode節點在擴展性和性能上的瓶頸,讓以前因 爲單Master節點帶來的種種問題全部都迎刃而解。同時也爲將來集羣的進一步擴充留下很大的餘地。基本上,在基於跨機房的那個版本和框架下,雲梯 Hadoop集羣幾乎是沒有物理上限的一個集羣了。

細心的讀者肯定發現,難點5的解決方案沒有詳細說明,下面對此進行詳細講述。

問題:在上述第三步中,我們怎樣將NameNode1中的部分數據(比如50%)遷移到NameNode2,遷移的同時還不影響業務的正常運行呢?(這裏的遷移包括NameSpace中的元數據遷移和底下DataNode磁盤中的block)。這個問題本身是一個非常複雜的場景,雲梯開發團隊也是通過幾個步 驟來一點點地實現的。

需要先讓新的NameNode2獲取原先NameNode1上所有的元數據的全量拷貝。這是開發團隊通過將 NameNode1上最新的fsimage用到NameNode2上,並進行load來完成的。這樣,新的NameNode2就擁有了NameNode1上所有的文件和目錄結構,以及文件的block組成情況,唯一缺的就是每個block在哪些DataNode上的分佈情況,這一部分需要通過 DataNode的blockReport來進行構建。

完成了上述步驟以後,還需要讓所有的DataNode上原本的單一 BlockPool變成多個。其中BlockPool1對應原先的DataNode上所有block數據的全量,而BlockPool2則是空。要讓 BlockPool2中擁有BlockPool1中的所有block,有兩種方式:一種是進行全量拷貝;另一種方式比較討巧,是將BlockPool1中 的所有block及其對應的目錄在BlockPool2中創建全量的hardlink。由於只是磁盤層面的硬連接創建,所以不佔額外的存儲空間,而且很 快。這樣,當所有的DataNode啓動時,原本的BlockPool1中的數據向NameNode1彙報,而BlockPool2中擁有的同樣一份數據 向NameNode2彙報。這樣當集羣啓動完畢以後,兩個NameNode都擁有整個集羣數據的元數據全量,只不過底層的存儲只有一份,通過硬連接來實現 block塊數據共享。

完成上一步後,集羣的狀態是:兩個NameNode都管理了整個集羣的全量數據,但實際上數據切分並不是要讓兩個 NameNode都管理全量數據,而是分別管理一半的數據(或者根據實際訪問需求來進行特定花費)。也就是說,NameNode1上雖然管理了全量,但需 要刪掉一部分不由它管理的數據,NameNode2也是一樣,而兩個NameNode管理的數據的總和就是原本的全量數據。由於底層block進行了硬連 接的創建,所以只要不在兩個NameNode上都刪掉同一份數據,那麼數據本身在DataNode上就不會丟失。接下來還需要完成兩件事:第一,客戶端能 根據不同的目錄訪問特定的NameNode(數據切分);第二,將仍在A機房但需要遷移到B機房的那部分數據(NameNode2應該管理的那部分數據) 的block塊遷移到B機房。

對於上述第一點,讓客戶端對不同數據的訪問自動找到相應的NameNode,是通過前述的ViewFS來實現 的。而對上述的第二點,對數據的實際遷移過程,則是通過雲梯開發團隊全新開發的一個新的Master組件——CrossNode來實現的。圖4是 CrossNode的架構圖。


圖4 雲梯CrossNode架構圖

CrossNode 是一個全新獨立的Master節點,它所管理的是:讀取一個配置文件,這個配置文件中記錄了哪些文件和目錄下的數據需要跨機房放置。例如,一個文件原本有 3個副本,都在A機房,把這個文件的路徑寫入到CrossNode的配置文件中,讓CrossNode知道這個文件需要跨機房放置,並且在A機房是3個副 本,B機房需要2個副本,主角CrossNode只負責從A機房拷貝2個副本到B機房。同時由於在跨機房那個目錄中會有新的文件被創建和寫入,所以這些目 錄下的文件在寫入完成後,也需要後期對其進行跨機房副本放置的處理,這些也都是CrossNode來完成的。

因此,將NameNode2需 要管理的那部分數據從A機房遷移到B機房的方式爲:將這些文件和目錄配置到CrossNode的配置文件中,這樣CrossNode就會發現有那麼多的數 據需要在A機房和B機房同時放置,如3:3,於是會對這些數據的block進行跨機房拷貝,直到所有的block全部在B機房擁有3個副本,然後將 CrossNode中的配置進行修改,例如修改成0:3,這樣表示A機房需要0個副本,B機房需要3個。於是CrossNode重新工作,將A機房原本的 3個副本進行刪除,保留B機房的3個副本,支持完成NameNode2管理的所有數據從A機房到B機房的遷移。大家可以發現,這個CrossNode的方 案,正好解決了難點2,因爲有了CrossNode以後,數據的遷移變成了一個計算的前序操作,每天雲梯系統會根據前一天的計算分佈和其他業務情況來決定 哪些文件需要跨機房分佈,哪些需要進行遷移,哪些需要去除跨機房分佈。這樣在計算真正運行時,絕大部分計算job需要的數據都會存在於計算調度所在的本機 房內,並不需要跨機房讀取和跨機房寫入,這樣機房間的帶寬並不會成爲影響計算作業效率的瓶頸。即使只有少量需要跨機房讀寫的訪問存在的情況下,機房間的帶 寬也完全能夠處理得過來。

總結

至此,經過上述一系列步驟, 便實現了雲梯Hadoop集羣的跨機房服務。目前,雲梯集羣規模已接近萬臺,跨越兩個IDC機房,數據的分佈和計算的調度每天都在根據實際情況進行實時調 整。跨機房雲梯的更重要意義在於:在未來的時間裏,阿里集團運行在Hadoop平臺上的大數據業務不需要再爲數據規模和性能而擔驚受怕,在雲梯現有的架構 下,已經基本看不到集羣規模的上限,性能也可以根據實際情況和訪問情況來進行動態的調整。

在過去五年中,阿里雲梯一直都採取需求驅動的發展模式。直到2013年4月,這種模式再也無法繼續下去:雲梯集羣所在的數據中心(IDC機房)的機位已滿,無法繼續擴充集羣,不能滿足阿里集團數據量增長的需求。此時,構建一個跨機房的Hadoop集羣便刻不容緩。 

作者羅李,花名鬼厲,阿里分佈式團隊創建之初的第一批員工,從事分佈式計算、分佈式存儲和Hadoop系統的研發,目前負責分佈式存儲團隊的所有技術和管理。

發佈了132 篇原創文章 · 獲贊 10 · 訪問量 41萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章