淘寶云梯的多NameNode和跨機房之路

jopen 10年前發布 | 13K 次閱讀 云梯 分布式/云計算/大數據

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所示。這一步是一個非常大的難點。

淘寶云梯的多NameNode和跨機房之路

圖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系統的研發,目前負責分布式存儲團隊的所有技術和管理。 

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!