騰訊上萬節點大規模叢集的跨城自動遷移

騰訊大資料發表於2017-06-07

前言

本文為騰訊移動分析MTA團隊運維工程師方錦亮的分享

作者在騰訊一直從事資料相關領域的系統運營和運營平臺的建設工作。目前主要負責 TDW 的系統運營,TDW 是騰訊內部最大的離線處理平臺,也是國內最大的 HADOOP 叢集之一。
在運營這麼大叢集的時候,運營面臨各種各樣的難題,在解決這些難題的過程中,團隊提煉出來的一個運營理念,用兩句話去描述。

1.用建模的思路去解決運營的難題
運營的問題怎麼解決?你必須用一些資料建模的辦法,把這個難題解析清楚,然後我們再去考慮運營平臺建設。

2.運營平臺支撐模型運作
不是為了建設運營平臺而建設,而是它必須有一定的運營理念。下文寫到這樣的運營理念是怎麼貫穿在遷移平臺的建設裡面的。

本文主題主要包含以下幾個方面:

介紹一下騰訊大規模叢集 TDW,以及為什麼做遷移。
我們的遷移模型是怎麼樣的。
遷移平臺是怎麼做的。
遷移策略

1、騰訊大規模叢集TDW

先介紹一下騰訊大規模叢集,我們這裡講的叢集是指 TDW。TDW 是騰訊分散式資料倉儲,它是一個海量資料儲存和計算平臺。
為什麼說是大規模叢集?
記得我剛開始接手 TDW 運營的時候,很多年前,當時我們有400臺的叢集,覺得我們叢集已經很大了,但是過了幾年之後,我們要運營的叢集已經達到4400臺。
現在看來4400臺還算挺大的,但是又過了幾年後,我們規模到了8800臺,這是我們的現狀。我們的現狀可以用三個指標來描述:

單叢集 8800 臺
支撐每天 20PB 掃描量
同時提供 200PB 儲存能力

所以我們說是“大”,用蘋果一句話說,biger than biger,我們預計到2017年底我們規模會達到2萬臺。
運營這麼大規模的叢集,運營人員自然會面臨很多挑戰。比如像裝置運維、版本上線變更、配置管理、還有快速擴容等等。這些問題,我們都有相應系統去支撐,本文說的是我們遇到的另外一個頭痛的問題:
叢集不斷膨脹,從400臺到8800臺,前期可以通過擴容解決。到目前這個階段,8800臺之後,我們發現擴容已經搞不定了。
為什麼?
因為現有機房的容量和網路架構只能支撐這麼大的規模,這時候我們需要將 TDW 遷移到其他城市更大容量的機房,這也就是我們面臨的另一個問題,跨城遷移。

1.1 騰訊大資料處理平臺整體架構

上文說了 TDW 的遷移原因,現在回過頭來看 TDW 的整體架構。TDW 是騰訊大資料的處理平臺的一部分,整個騰訊大資料處理平臺包含了下面五層。

騰訊大資料平臺整體架構
騰訊大資料平臺整體架構

我們從下往上看:

最底層是資料儲存層,包括 HDFS、HBase、Ceph、PGXZ;
第二層是資源排程層;
第三層是計算引擎層,包括 MR、Spark 和 GPU;
第四層是計算框架,包括 Hermes、Hive、Pig、SparkSQL、GraphX 等;
最上層是服務層,提供給外部資料分析能力和機器學習能力。

這是整個騰訊大資料平臺,剛才說的 8800 覆蓋了其中離線資料處理的部分。我們整個遷移覆蓋了 HDFS、蓋婭、MR、SPARK、HIVE、Pig 和 SparkSQL。

2、我們的遷移模型是怎樣的?

2.1 跨城資料遷移到底難在哪裡?

首先是運維工作量非常大。有上百P的資料要騰挪,有幾十萬任務需要切換,還有近萬臺的裝置需要搬遷,這個事情對於運維來說工作量非常大。

其次,要保障業務無感知。遷移過程中系統要穩定可用,要保障資料不能丟失,不能把一份資料從一個地方搬遷到另外一個地方的時候,把資料弄丟了。

最後,要保障任務的計算結果準確而且任務的執行時長不能有明顯的波動。

不管是運維工作量大還是業務無感知,這都還不是最致命的,對於跨城遷移來說,最致命的問題是:
當資料和計算分散在兩個城市的時候,資料穿越可能造成專線阻塞,從而影響使用專線的所有系統,導致影響擴大化。

在介紹跨城遷移模型之前,我們先簡單介紹兩個方案,一個是雙叢集方案,一個是單叢集方案。

方案一:雙叢集方案
雙叢集方案比較好理解,左側跟右側是兩個城市的叢集,雙叢集方案就是兩套完全獨立的系統,讓它們獨立去跑。

雙叢集方案
雙叢集方案

在說方案之前,我再深入介紹一下 TDW 裡面的幾個模組。我們只看左邊就可以了。
左邊從下面最底層是 GAIA,GAIA 負責資源排程。中間最左側是資料採集 TDBank,它負責把各個業務線資料收集到 TDW。
TDW 的核心是計算引擎和儲存引擎,儲存引擎是放資料的地方,計算引擎提供 MapReduce 和 Spark 的計算能力。之上有查詢引擎,最上面提供兩個使用者入口,任務統一排程和整合開發環境 IDE。
我舉兩個例子來說說各模組是怎麼互動的。

案例一,資料是怎麼進入 TDW 的?

首先業務資料經過資料採集模組,落地到儲存引擎的某個目錄下;統一任務排程 Lhotse 配置的一個入庫任務,與 Hive 互動,將目錄的資料轉換成 Hive 表的資料。

案例二,資料是怎麼計算的?

資料計算通過任務觸發,任務是對資料的處理加工,比如統計日報的時候,計算任務對某個表做操作,把結果寫回到另一個表中。

遷移是把儲存和計算整套 TDW 平臺,從一個城市搬遷到另外一個城市,雙叢集方案思路就很簡單,在另外一個城市把所有系統都搭起來,跑起來就好了。
系統在兩個城市之間是完全獨立的,比如資料兩份,計算兩份,在這兩個獨立的系統之間不需要有任何的資料穿越(除了在遷移本身的資料穿越)。
這個方案最大優點就是不需要資料穿越,業務可以做到完全無影響,但是它最大缺點是需要大量的冗餘裝置。

方案二:單叢集方案

下面講一下單叢集方案,它跟雙叢集差異點在哪裡?
最核心的差別在於:儲存不會同時在兩個地方,要麼在左邊,要麼在右邊。

單叢集方案
單叢集方案

單叢集方案有一個最大的優點就是不需要大量的裝置,慢慢地把一部分裝置,一部分業務,從左邊遷移到右邊。
這裡會面臨一個問題,比如剛才說到的一個計算的場景,如果沒有控制好的話,會出現計算在左側,資料已經跑到右側去了,因為資料只有一份。任務跑起來的時候,左側的計算引擎就會大量拉取右側的資料,會對專線造成很大的風險。
對比一下剛才那兩個方案,我們可以總結一下思路:在一個大的系統裡,如果優先考慮成本,建議採用單叢集方案。

單叢集方案最大風險是跨城流量控制,跨城流量控制最重要的點是:資料在哪裡,計算就去哪裡,要不然就是穿越;如果訪問的資料兩邊都有,哪邊資料量大,計算就在哪邊。

2.2 建立基於關係鏈的遷移模型

前面我們分析了一下我們實現跨城遷移的問題和方案,接下來我們為了解決跨城的流量控制降低跨城遷移的流量,我們引入一個基於關係鏈的遷移模型。

一個關係鏈的例子
一個關係鏈的例子

我們需要知道資料流是怎麼樣來的,比如上面的一個關係鏈中,入庫任務對最頂層的 HDFS 資料做一些加工處理,處理之後把結果儲存到入庫表;
分析人員基於這個入庫表做各種計算和統計分析,比如統計某些指標,做關聯性分析,這裡配置了四個任務,這四個任務執行後產生新的結果表,其中還有兩個結果表由下層的任務做進一步的處理,這樣就產生了資料和任務的關係鏈。
引入關係鏈模型,它能幫助我們理清楚資料和任務的關係。
我們用橢圓描述資料,矩形描述對資料的加工,他們的連線表明訪問資料的方向,是讀還是寫。這個關係可以用來指導我們的資料遷移,可以做到資料在哪裡,計算就在哪裡。

2.3 關係鏈的生成

接著的問題是在一個大的系統裡關係鏈怎麼生成?
在任務排程裡面有一個概念,叫做依賴,用來描述任務的父子關係,父任務執行完成後子任務才允許執行。
原來我們沒有做關係鏈的時候,這是純粹的任務排程層的關係,雖然它有一定指導作用,但是不能直接應用在遷移裡面,因為我們需要的是資料和任務的關係,而不僅是任務和任務的關係,我們需要從龐大的任務管理系統生成關係鏈,來指導資料遷移。
接下來介紹一個叫 hadoopdoctor 的運營工具,它是用做什麼的?
它會把我們跑的任務資訊採集回來,把它儲存在 DB 裡面,這些資訊用於定位 MR 失敗原因或效能分析。
它有一個主控模組,每五分鐘去所有的 NodeManager 採集每個 MR 的配置和執行資訊,比如說它的訪問資料是什麼,輸出結果是什麼。
為了支援遷移,我們改了一些邏輯,讓 hadoopdocter 記錄資料路徑和任務ID,同時區分標識是讀的還是寫的。
把這個資料採集出來以後,我們就可以做關係鏈的分析。

hadoopdoctor架構
hadoopdoctor架構

這裡面採集到的路徑會非常多,比如一個日報可能訪問的是昨天某一個表的資料,比如訪問量,就需要訪問昨天的分割槽。採集出來的資料路徑粒度非常細,它是包含日期的。
但是我們關注點並不需要到分割槽,我們關注的是表本身。所以我們把涉及到日期相關的路徑規約掉,轉成與日期無關的路徑,資料規約對關係鏈分析有好處,歸完之後減少了很多的資料量。
我們把最基礎的資訊採集到,它描述了一個任務,訪問什麼資料,產生什麼資料。
經過我們的邏輯採集完之後,我們得到的是最原子的資料訪問關係,就是一個任務對儲存的操作,讀或者是寫,我們會產生非常多這樣的原子關係,這種關係累計的結果就是關係鏈。
我們清洗出來一個最基礎的關係,可以拼湊成一個大的關係鏈。

2.4 切分大關係鏈

關係鏈裡面特別注意的地方,是一定要覆蓋全面。
統計分析裡不僅有日報,還有周報和月報,統計週期一定要覆蓋較長的時間範圍,這樣才能把所有關係描述準確。
從最基礎的原子關係聚合成關係鏈,可以用並查集演算法。聚合出來的關係鏈,有大有小。對於小的關係鏈,很簡單就可以把它遷走;但是我們發現一個很頭痛的問題,聚合除了產生很多小的關係鏈,同時也產生了少量非常大的關係鏈,一個大的關係鏈可能包括超過十萬個結點。
這時候我們發現回到原點,本來想把整個資料倉儲從一個城市挪到另外一個城市,思路是將它打散生成多個關係鏈,最後也確實產生一些小的關係鏈,方便我們做遷移。但是遺留了一些大的關係鏈。

一個大關係鏈的切分
一個大關係鏈的切分

如果看這個圖我們自然而然想:既然這麼大的關係鏈遷不動,就先遷上面部分,這裡就是把大的關係鏈切開的想法。

我們引入一些關鍵結點,這些關鍵點把大的關係鏈切分成多個小關係鏈。

那麼哪個關係鏈結點才是最合適的?這個也很難找,大家可以想理論上是存在的,比如從圖中標紅色部分一刀切過去就可以一分為二,但是在上十萬結點規模的關係鏈裡是很難做到這個事情的。

2.5 引入HIVE雙寫表

把這個問題先留在後面,我們先做一個假設,已經找到合適的結點了,怎麼實施關鍵結點的遷移,有兩種思路:
一種是單份資料方案,比如把這份資料遷到另外一個城市,就讓它穿越,很容易實現,但是不好控制流量;
另一種是雙份資料方案,把關係鏈一分為二的時候,就把關鍵結點的資料變成兩份。我們引入雙寫表的概念,雙寫表有兩個 location。

雙寫表和同步任務
雙寫表和同步任務

雙寫表的資料有兩份,在城市A訪問資料的時候,城市A 的 HIVE 會返到主的 location,城市B則返回備的 location,計算可以訪問離自己近的儲存。
這裡,需要一個任務把城市A的資料同步到城市B中,這是一個同步任務,這個任務在資料在城市A生成後(總有個計算任務往裡面寫資料),把城市A的資料同步到城市B,保證兩邊的資料是一致的。
在遷移過程中把一個表升級成雙寫表的過程業務是無感知的,我們有機制保證資料雙份,就近訪問。

2.6 資料一致性保證

剛才說到雙寫表在城市A和城市B有兩份資料,由同步任務負責同步,這時候我們會遇到一個問題,在城市A和城市B,它的下游任務會不會在同步任務沒跑完之前就去訪問這個資料?

資料流轉過程的任務依賴
資料流轉過程的任務依賴

我們必須要保證資料的一致性,這通過增加對同步任務的依賴實現。
比如任務產生資料表1,下面三個任務會讀取表1資料,這個依賴關係是上面這個任務是父任務,只有這個父任務跑完之後,下面三個子任務才能跑起來。這個依賴邏輯保證了三個子任務總能正確訪問表-1的資料。


加入了同步任務之後,我們就保證了資料的一致性。比如這個圖裡,我們有兩個任務從城市A遷到城市B,這時候我們要保持資料和計算的一致性,只需要保證城市B訪問表-1資料的任務依賴同步任務即可。

2.7 最小化切分和關係鏈融合

回到一個大的關係鏈怎麼拆分的問題,假設已經把它拆開了。
拆開的時候產生了很多小的關係鏈,把小的關係鏈從一個城市遷移到另外一個城市的時候,為了減少資料穿量引入雙寫表的概念,雙寫表加上任務依賴,保證了所有拆分出來的關係鏈有一個比較非常好的特性,就是不管產生多少個關係鏈,每個關係鏈都是隨時可以遷移的。
還有一個問題:我們很難找到合適的關鍵點,對一個十萬節點關係鏈,我們做了一些嘗試,用遍歷的方式查詢所有可行的雙寫表,都不能把這麼大的關係鏈拆開,我們發現不存在單個雙寫表可以拆開這麼複雜的關係鏈。
大家可以想象一下,一個很複雜的圖裡面可能找不到一個結點能夠將它切分成多個關係鏈。單個雙寫表做不到,則需要使用多個雙寫表,這時候找出合適雙寫表的演算法就會非常複雜。
後來我們做了一個變通,讓所有符合雙寫表規則的表都變成雙寫表,這樣可以實現對一個大關係鏈的最小化拆分。之後我們對最小化拆分後的小關係鏈又做了融合,把很小的關係鏈併成規模適中的關係鏈。
這裡面整體的思路,類似於工廠流水線打包,我們把關係鏈聚合,再把它拆分融合,變成一個個大小適中的關係鏈,就像工廠打包的一個個箱子,遷移就是把這些箱從從城市A運輸到城市B的過程。

2.8 計算的遷移

我再補充一下計算的遷移,剛才上面架構裡面,說計算需要從城市A遷移城市B,怎麼切呢?
我們對每個任務加上城市 ID 的擴充套件引數,當這個任務需要從城市A切到城市B跑的時候,只需要改這個引數就好了。平臺會記錄城市 ID,並在不同系統上傳遞,進行準確的路由,這樣實現任務是方便遷移的。

任務遷移的路由
任務遷移的路由

我再總結一下遷移模型,我們面臨運營上很頭疼的事情,要做跨城遷移,我們解決的方案是基於關係鏈,把關係鏈打散,通過機制保證關係鏈的一致性,使得我們遷移能夠跑起來。

3、跨城遷移平臺的建立

剛才我們說的是模型,有一套模型指導我們做遷移這個事情,有了模型之後,需要一個平臺來支撐這個模型。
關係從無到有,對最基礎的關係進行聚合,形成關係鏈。找關係鏈的核心結點,把關係鏈拆分,將小的關係鏈融合成更大的關係鏈。遷移平臺有一個模組專門負責關係鏈的這類操作。
另外一個模組是關係鏈的遷移模組,就是怎麼把已經劃分好的關係鏈從一個城市挪到另外一個城市,它涉及資料的遷移,任務的切換,普通表升級雙寫表,依賴任務和同步任務的處理。
此外還有一個模組是平臺保障,資料校驗,任務校驗和跨城流量的監控。

3.1 關係鏈遷移模組

遷移模型解決了一件事情,就是從無到有,構造我們的關係鏈,然後把關係鏈從大拆小,拆到合適遷移一個個的規模適中的關係鏈。
關係鏈遷移是解決另外一個問題。一個關係鏈裡包含任務和資料,在遷移過程中,它們的狀態會變化。比如說資料還在寫,TDW 的資料每天在不斷變化。任務也可能還正在跑,沒有結束。
也就是說,關係鏈並不是靜止的狀態,它是動態變化的。關係鏈遷移是要保障在動態變化的環境下,資料和任務的遷移是準確的。

關係鏈遷移模組的狀態變遷
關係鏈遷移模組的狀態變遷

關係鏈遷移時,首先會看關係鏈裡有什麼雙寫表,先處理雙寫表,之後處理其他資料的遷移。資料遷移時,先按表分割槽展開,按分割槽遷移,這可以加快遷移的速度。
遷移開始前會通知使用者,使用者可以不用管,但是他需要被通知到。如果遇到什麼異常,使用者可以分析是不是因為這個變化導致。
通知完使用者,會展開所有表的分割槽,對展開之後的分割槽做遷移操作,也就是 distcp。
當 distcp 到一定進度的時候,會做凍結任務的操作。關係鏈裡面的任務可能有狀態變化,凍結操作可以將其轉變成不可變的狀態。
把資料的寫入任務凍結,寫入任務可以通過關係鏈找到,如果沒有關係鏈這種凍結操作也無法實施。遷移的過程不允許任務進行寫入操作,因為寫入操作會導致資料很難保證一致性。
把任務凍結之後進入等待資料一致的狀態,在這個狀態裡還會不斷對比兩個城市之間的資料差異。
比如新增資料,資料不一樣了就會再做一次資料同步的工作,直到資料完全一致,進入一致狀態的時候,資料遷移的工作就完成了。之後進行任務遷移,任務遷移後就可以解凍任務,完成整個關係鏈的遷移。
這裡最重要的是有一個凍結任務的邏輯,保證我們在資料遷移的時候,有一個時間段不會有任務在修改資料。凍結任務的時間越短越好,這就要求資料遷移的速度越快越好。
資料倉儲裡的表佔用空間有大有小,對於大表,直接進行表級 distcp 的時候,通常起的 map 數很少,這時候併發上不來,速度也上不來。所以對於大表,需要採用分割槽級的 distcp。對於小表則相反,分割槽級的 distcp 往往是浪費。
另外關係鏈的遷移需要支援併發,關係鏈的在遷移過程消耗的資源不一樣,有時候是網路流量大有時候網路流量小。關係鏈併發遷移,可以規避這種情況,實現接近滿負載流量的遷移。

3.2 平臺保障模組

平臺保障模組,包括兩大塊的保障:一個是基礎保障,還有是監控保障。

基礎保障
做了兩件事情,一個是資料校驗,遷移完成兩邊資料要做校驗,另外一件事情是任務的抽樣重跑。我們引入一個思路,在關係鏈裡面抽出一條垂直的路徑,從根節點一路下來重做任務。

一個關係鏈可能有幾十個結點,抽樣後只有四五個結點。對抽樣出來的結點進行重跑,重跑後做資料比對,看看是不是一致的。這樣可以保證資料是準確的,任務也是準確的。

監控保障
做了幾件事情,一個是資料量的監控,遷移完成後,監控資料量的波動,看看資料量跟之前的是不是有明顯波動。另外會監控所有遷移過的任務,看看它們在新的城市是否執行正常。

最後,是流量的異常監控。資料和任務都驗證成功,遷移也就是成功的了。資料已經從一個城市整體遷移到另外一個城市,任務也一起切換過來。最後要考慮的是,會不會有異常情況導致我們的跨城流量出現異常上漲。

我們有一個流量監控的機制,來解決一些例外情況導致的流量異常。通過加強流量的異常監控,並實現任務的自動切換。每五分鐘採集正在執行的所有任務,以及它們訪問的資料。
如果發現有任務在城市A的計算叢集裡面跑,但是它訪問了城市B的資料,這種異常的情況會被監控起來。當資料穿越流量過高時,會自動把任務殺掉,同時自動進行任務切換。

4、跨城遷移平臺的遷移策略

我們已經介紹了遷移模型和遷移平臺,我們有一套模型去解決我們的運營面臨跨城遷移的難點,然後我們也有一個平臺支撐這個關係鏈遷移的邏輯。接下來我要再講一下我們的遷移策略。

4.1 遷移叢集獨立部署

遷移叢集需要獨立部署,遷移最大的工作量是資料遷移,有很多資料要從一個地方同步到另外一個地方,資料遷移的方式就是做 distcp,distcp 是一個MR任務,MR 任務需要消耗計算資源。遷移叢集最好獨立開來,這樣就不會影響正常的排程任務。
遷移叢集最大的特點是網路流量會跑得很高,因為它只做一件事情,從源叢集拉取資料,寫到目標叢集,觀察遷移叢集的網路流量的時候就會發現,它跑起來的時候,出入流量是一樣的,它是網路流量高消耗的叢集。
它有一個特點,它是低CPU消耗的叢集。把它單獨做為遷移叢集,可以做到兩個特性化配置,一個就是採用高網路配置的機型,比如使用萬兆網路卡的機型。另一個是採用低記憶體的任務配置以及對遷移叢集的計算節點採用高併發的配置。
這樣可以在儘量減少遷移叢集的裝置需求量的同時,大大提升遷移速度。我們採用40臺機器的遷移叢集就能支撐1P的遷移流量。

4.2 遷移的流量控制

採用獨立的遷移計算叢集
採用獨立的遷移計算叢集

遷移的流量控制,這張圖很有意思的地方是,當我們做資料遷移的時候,源叢集(城市A HDFS叢集),遷移計算叢集,目標叢集(城市B HDFS叢集),這三個叢集的流量有很有意思的關係。
源叢集是一個大叢集,通常有上千臺機器;遷移計算叢集則少得多,可能只有幾十臺。遷移計算叢集在網路打滿的情況下,對源叢集的網路消耗可以計算出來,對目標叢集的網路消耗也是可以計算出來的。
舉個例子,如果遷移計算叢集有40臺的規模,這40臺裝置的網路用滿的時候,源叢集如果只有400臺,網路也會被用滿,網路用滿的時候會對任務一定會有影響。
還有一個比較有意思的事情,目標叢集的流量要比遷移叢集流量大,原因是寫資料時 Hadoop 有多份拷貝,會導致目標叢集的流量翻倍增加。我們在使用遷移叢集的時候,可以對遷移叢集進行資源池管理,限定它的資源池大小,也就是限定遷移最大的併發數,從而對遷移流量進行控制。

4.3 叢集的同步任務

再說說同步任務,同步任務對流量影響會比較小,因為同步任務方向和遷移方向是反方向的,遷移方向是城市A到城市B,同步任務是逆向回來的,所以流量很小。
我們儘量降低同步任務對業務的影響,建議使用獨立的同步任務資源池,這個資源池可以更大一些,讓同步任務快速完成,不影響其他任務。

4.4 HDFS叢集的縮容擴容策略

最後,HDFS 叢集的縮容擴容策略,在叢集縮容的時候,要優先考慮叢集整體下線,在縮容前要先進行資料清理和小檔案合併。
另外,遷移的時候裝置是一批批搬遷的,比如每一輪搬遷200臺機器。這200臺擴容到目標叢集的時候,新擴容的節點在一段時間內不參與計算。因為 Hadoop 的 balance 機制會導致新擴容機器的網路流量被打滿,直接影響計算任務的速度。

關於我們

騰訊大資料團隊官方公眾號,關注大資料平臺構建、資料探勘、資料應用等。促進資訊共享及行業交流。

歡迎關注“騰訊大資料”公眾號,瞭解更多大資料相關資訊

相關文章