有贊大資料離線叢集遷移實戰

大資料頻道發表於2020-07-30



有贊大資料離線叢集遷移實戰
者:郭理想 & 任海潮
部門:資料中臺

一、背景

有贊是一家商家服務公司,向商家提供強大的基於社交網路的,全渠道經營的 SaaS 系統和一體化新零售解決方案。隨著近年來社交電商的火爆,有贊大資料叢集一直處於快速增長的狀態。在 2019 年下半年,原有云廠商的機房已經不能滿足未來幾年的持續擴容的需要,同時考慮到提升機器擴容的效率(減少等待機器到位的時間)以及支援彈性伸縮容的能力,我們決定將大資料離線 Hadoop 叢集整體遷移到其他雲廠商。
在遷移前我們的離線叢集規模已經達到 200+ 物理機器,每天 40000+ 排程任務,本次遷移的目標如下:
  • 將 Hadoop 上的資料從原有機房在有限時間內全量遷移到新的機房
  • 如果全量遷移資料期間有新增或者更新的資料,需要識別出來並增量遷移
  • 對遷移前後的資料,要能對比驗證一致性(不能出現資料缺失、髒資料等情況)
  • 遷移期間(可能持續幾個月),保證上層執行任務的成功和結果資料的正確

有贊大資料離線平臺技術架構

上文說了 Hadoop 叢集遷移的背景和目的,我們回過頭來再看下目前有贊大資料離線平臺整體的技術架構,如圖1.1所示,從低往上看依次包括:
有贊大資料離線叢集遷移實戰
圖1.1 有贊大資料離線平臺的技術架構
  • Hadoop 生態相關基礎設施,包括 HDFS、YARN、Spark、Hive、Presto、HBase、Kafka、Kylin等
  • 基礎元件,包括 Airflow (排程)、DataX (離線資料同步)、基於binlog的增量資料同步、SQL解析/執行引擎選擇服務、監控&診斷等
  • 平臺層面,包括: 資料開發平臺(下文簡稱DP)、資產管理平臺、資料視覺化平臺、演算法訓練平臺等
本次遷移會涉及到從底層基礎設施到上層平臺各個層面的工作。

二、方案調研

在開始遷移之前,我們調研了業界在遷移 Hadoop 叢集時,常用的幾種方案:

2.1 單叢集

兩個機房公用一個 Hadoop 叢集(同一個Active NameNode,DataNode節點進行雙機房部署),具體來講有兩種實現方式:
  • (記為方案A) 新機房DataNode節點逐步擴容,老機房DataNode節點逐步縮容,縮容之後透過 HDFS 原生工具 Balancer 實現 HDFS Block 副本的動態均衡,最後將Active NameNode切換到新機房部署,完成遷移。這種方式最為簡單,但是存在跨機房拉取 Shuffle 資料、HDFS 檔案讀取等導致的專線頻寬耗盡的風險,如圖2.1所示
  • (記為方案B) 方案 A 由於兩個機房之間有大量的網路傳輸,實際跨機房專線頻寬較少情況下一般不會採納,另外一種頻寬更加友好的方案是:
  • 透過Hadoop 的 Rack Awareness 來實現 HDFS Block N副本雙機房按比例分佈(透過調整 HDFS 資料塊副本放置策略,比如常用3副本,兩個機房比例為1:2)
  • 透過工具(需要自研)來保證 HDFS Block 副本按比例在兩個機房間的分佈(思路是:透過 NameNode 拉取 FSImage,讀取每個 HDFS Block 副本的機房分佈情況,然後在預定限速下,實現副本的均衡)
有贊大資料離線叢集遷移實戰
圖2.1 單叢集遷移方案
優點:
  • 對使用者透明,基本無需業務方投入
  • 資料一致性好
  • 相比多叢集,機器成本比較低
缺點:
  • 需要比較大的跨機房專線頻寬,保證每天增量資料的同步和 Shuffle 資料拉取的需要
  • 需要改造基礎元件(Hadoop/Spark)來支援本機房優先讀寫、在限速下實現跨機房副本按比例分佈等
  • 最後在完成遷移之前,需要集中進行 Namenode、ResourceManager 等切換,有變更風險

2.2 多叢集

在新機房搭建一套新的 Hadoop 叢集,第一次將全量 HDFS 資料透過 Distcp 複製到新叢集,之後保證增量的資料複製直至兩邊的資料完全一致,完成切換並把老的叢集下線,如圖2.2所示。
這種場景也有兩種不同的實施方式:
  • (記為方案C) 兩邊 HDFS 資料完全一致後,一鍵全部切換(比如透過在DP上配置改成指向新叢集),優點是使用者基本無感知,缺點也比較明顯,一鍵遷移的風險極大(怎麼保證兩邊完全一致、怎麼快速識別&快速回滾)
  • (記為方案D) 按照DP上的任務血緣關係,分層(比如按照資料倉儲分層依次遷移 ODS / DW / DM 層資料)、分不同業務線遷移,優點是風險較低(分治)且可控,缺點是使用者感知較為明顯
有贊大資料離線叢集遷移實戰
圖2.2 多叢集遷移方案
優點:
  • 跨機房專線頻寬要求不高(第一次全量同步期間不跑任務,後續增量資料同步,兩邊雙跑任務不存在跨機房 Shuffle 問題)
  • 風險可控,可以分階段(ODS / DW / DM)依次遷移,每個階段可以驗證資料一致性後再開始下一階段的遷移
  • 不需要改造基礎元件(Hadoop/Spark)
缺點:
  • 對使用者不透明,需要業務方配合
  • 在平臺層需要提供工具,來實現低成本遷移、資料一致性校驗等

2.3 方案評估

從使用者感知透明度來考慮,我們肯定會優先考慮單叢集方案,因為單叢集在遷移過程中,能做到基本對使用者無感知的狀態,但是考慮到如下幾個方面的因素,我們最終還是選擇了多叢集方案:
  • (主因)跨機房的專線頻寬大小不足。上述單叢集的方案 A 在 Shuffle 過程中需要大量的頻寬使用;方案 B 雖然頻寬更加可控些,但副本跨機房複製還是需要不少頻寬,同時前期的基礎設施改造成本較大
  • (次因)平臺上的任務型別眾多,之前也沒系統性梳理過,透明的一鍵遷移可能會產生穩定性問題,同時較難做回滾操作
因此我們透過評估,最終採用了方案 D。

三、實施過程

在方案確定後,我們便開始了有條不紊的遷移工作,整體的流程如圖3.1所示
有贊大資料離線叢集遷移實戰
圖3.1 離線Hadoop多叢集跨機房遷移流程圖
上述遷移流程中,核心要解決幾個問題:
  • 第一次全量Hadoop資料複製到新叢集,如何保證過程的可控(有限時間內完成、限速、資料一致、識別更新資料)?(工具保證)
  • 離線任務的遷移,如何做到較低的遷移成本,且保障遷移期間任務程式碼、資料完全一致?(平臺保證)
  • 完全遷移的條件怎麼確定?如何降低整體的風險?(重要考慮點)

3.1 Hadoop 全量資料複製

首先我們在新機房搭建了一套 Hadoop 叢集,在進行了效能壓測和容量評估後,使用 DistCp 工具在老叢集資源相對空閒的時間段做了 HDFS 資料的全量複製,此次複製 HDFS 資料時新叢集只開啟了單副本,整個全量同步持續了兩週。基於 DistCp 本身的特性(頻寬限制:-bandwidth / 基於修改時間和大小的比較和更新:-update)較好的滿足全量資料複製以及後續的增量更新的需求。

3.2 離線任務的遷移

目前有贊所有的大資料離線任務都是透過 DP 平臺來開發和排程的,由於底層採用了兩套 Hadoop 叢集的方案,所以遷移的核心工作變成了怎麼把 DP 平臺上任務遷移到新叢集。

3.2.1 DP 平臺介紹

有讚的 DP 平臺是提供使用者大資料離線開發所需的環境、工具以及資料的一站式平臺(更詳細的介紹請參考另一篇部落格),目前支援的任務主要包括:
  • 離線匯入任務( MySQL 全量/增量匯入到 Hive)
  • 基於binlog的增量匯入 (資料流:binlog -> Canal -> NSQ -> Flume -> HDFS -> Hive)
  • 匯出任務(Hive -> MySQL、Hive -> ElasticSearch、Hive -> HBase 等)
  • Hive SQL、Spark SQL 任務
  • Spark Jar、MapReduce 任務
  • 其他:比如指令碼任務
本次由於採用多叢集跨機房遷移方案(兩個 Hadoop 叢集),因此需要在新舊兩個機房搭建兩套 DP 平臺,同時由於遷移週期比較長(幾個月)且使用者遷移的時間節奏不一樣,因此會出現部分任務先遷完,部分任務還在雙跑,還有一些任務沒開始遷移的情況。

3.2.2 DP 任務狀態一致性保證

在新舊兩套 DP 平臺都允許使用者建立和更新任務的前提下,如何保證兩邊任務狀態一致呢(任務狀態不限於MySQL的資料、Gitlab的排程檔案等,因此不能簡單使用MySQL自帶的主從複製功能)?我們採取的方案是透過事件機制來實現任務操作時間的重放,展開來講:
  • 使用者在老 DP 產生的操作(包括新建/更新任務配置、任務測試/釋出/暫停等),透過事件匯流排產生事件訊息傳送到 Kafka,新系統透過訂閱 Kafka 訊息來實現事件的回放,如圖 3.2 所示。 
    有贊大資料離線叢集遷移實戰
    圖3.2 透過事件機制,來保證兩個平臺之間的任務狀態一致

3.2.3 DP 任務遷移狀態機設計

DP 底層的改造對使用者來說是透明的,最終暴露給使用者的僅是一個遷移介面,每個工作流的遷移動作由使用者來觸發。工作流的遷移分為兩個階段:雙跑和全部遷移,狀態流轉如圖 3.3 所示
有贊大資料離線叢集遷移實戰
圖 3.3 工作流遷移狀態流轉

雙跑

工作流的初始狀態為未遷移,然後使用者點選遷移按鈕,會彈出遷移介面,如圖 3.4 所示,使用者可以指定工作流的任意子任務的執行方式,主要選項如下:
  • 兩邊都跑:任務在新老環境都進行排程

  • 老環境跑:任務只在老環境進行排程

  • 新環境跑:任務只在新環境進行排程


有贊大資料離線叢集遷移實戰

圖 3.4 工作流點選遷移時,彈框提示選擇子任務需要執行的方式
不同型別的子任務建議的執行方式如下:
  • 匯入任務 (MySQL -> Hive):通常是雙跑,也就是兩個叢集在排程期間都會從業務方的 MySQL 拉取資料(由於拉取的是 Slave 庫,且全量拉取的一般是資料量不太大的表)

  • Hive、SparkSQL 任務:通常也是雙跑,雙跑時新老叢集都會進行計算。

  • MapReduce、Spark Jar 任務:需要業務方自行判斷:任務的輸出是否是冪等的、程式碼中是否配置了指向老叢集的地址資訊等

  • 匯出任務:一般而言無法雙跑,如果兩個環境的任務同時向同一個 MySQL表(或者 同一個ElasticSearch 索引)寫入/更新資料,容易造成資料不一致,建議在驗證了上游 Hive 表資料在兩個叢集一致性後進行切換(只在新環境跑)。

  • 同時處於使用者容易誤操作導致問題的考慮,DP 平臺在使用者設定任務執行方式後,進行必要的規則校驗:

  • 如果任務狀態是雙跑,則任務依賴的上游必須處於雙跑的狀態,否則進行報錯。

  • 如果任務是第一次雙跑,會使用 Distcp 將其產出的 Hive 表同步到新叢集,基於 Distcp 本身的特性,實際上只同步了在第一次同步之後的增量/修改資料。

  • 如果工作流要全部遷移(老環境不跑了),則工作流的下游必須已經全部遷移完。
雙跑期間的資料流向如下圖 3.5 所示:

有贊大資料離線叢集遷移實戰

圖 3.5 DP 任務雙跑期間資料流向

遷移過程中工作流操作的限制規則

由於某個工作流遷移的持續時間可能會比較長(比如DW層任務需要等到所有DM層任務全部遷移完),因此我們既要保證在遷移期間工作流可以繼續開發,同時也要做好預防誤操作的限制,具體規則如下:
  • 遷移中的工作流在老環境可以進行修改和釋出的,新環境則禁止
  • 工作流在老環境修改釋出後,會將修改的後設資料同步到新環境,同時對新環境中的工作流進行釋出。
  • 工作流全部遷移,需要所有的下游已經完成全部遷移。

3.3 有序推動業務方遷移

工具都已經開發好了,接下來就是推動 DP 上的業務方進行遷移,DP 上任務數量大、種類多、依賴複雜,推動業務方需要一定的策略和順序。有讚的資料倉儲設計是有一定規範的,所以我們可以按照任務依賴的上下游關係進行推動:
  • 匯入任務( MySQL 全量/增量匯入 Hive) 一般屬於資料倉儲的 ODS 層,可以進行全量雙跑。
  • 數倉中間層任務主要是 Hive / Spark SQL 任務,也可以全量雙跑,在驗證了新老叢集的 Hive 表一致性後,開始推動數倉業務方進行遷移。
  • 數倉業務方的任務一般是 Hive / Spark SQL 任務和匯出任務,先將自己的 Hive 任務雙跑,驗證資料一致性沒有問題後,使用者可以選擇對工作流進行全部遷移,此操作將整個工作流在新環境開始排程,老環境暫停排程。
  • 數倉業務方的工作流全部遷移完成後,將匯入任務和數倉中間層任務統一在老環境暫停排程。
  • 其他任務主要是 MapReduce、Spark Jar、指令碼任務,需要責任人自行評估。

3.4 過程保障

工具已經開發好,遷移計劃也已經確定,是不是可以讓業務進行遷移了呢?慢著,我們還少了一個很重要的環節,如何保證遷移的穩定呢?在遷移期間一旦出現 bug 那必將是一個很嚴重的故障。因此如何保證遷移的穩定性也是需要著重考慮的,經過仔細思考我們發現問題可以分為三類,遷移工具的穩定,資料一致性和快速回滾。

遷移工具穩定

  • 新 DP 的後設資料同步不及時或出現 Bug,導致新老環境後設資料不一致,最終跑出來的資料必定天差地別。
  • 應對措施:透過離線任務比對兩套 DP 中的後設資料,如果出現不一致,及時報警。
  • 工作流在老 DP 修改釋出後,新 DP 工作流沒釋出成功,導致兩邊排程的 airflow 指令碼不一致。
  • 應對措施:透過離線任務來比對 airflow 的指令碼,如果出現不一致,及時報警。
  • 全部遷移後老環境 DP 沒有暫定排程,導致匯出任務生成髒資料。
  • 應對措施:定時檢測全部遷移的工作流是否暫停排程。
  • 使用者設定的執行狀態和實際 airflow 指令碼的執行狀態不一致,比如使用者期望新環境空跑,但由於程式 bug 導致新環境沒有空跑。
  • 應對措施:透過離線任務來比對 airflow 的指令碼執行狀態和資料庫設定的狀態。

Hive 表資料一致性

Hive 表資料一致性指的是,雙跑任務產出的 Hive 表資料,如何檢查資料一致性以及識別出來不一致的資料的內容,具體方案如下(如圖3.6所示):
  • 雙跑的任務在每次排程執行完成後,我們會上報 <任務T、產出的表A> 資訊,用於資料質量校驗(DQC),等兩個叢集產出的表A都準備好了,就觸發資料一致性對比
  • 根據 <表名、表唯一鍵K> 引數提交一個 MapReduce Job,由於我們的 Hive 表格式都是以 Orc格式儲存,提交的 MapReduce Job 在 MapTask 中會讀取表的任意一個 Orc 檔案並得到 Orc Struct 資訊,根據使用者指定的表唯一鍵,來作為 Shuffle Key,這樣新老表的同一條記錄就會在同一個 ReduceTask 中處理,計算得到資料是否相同,如果不同則列印出差異的資料
  • 表資料比對不一致的結果會傳送給表的負責人,及時發現和定位問題
有贊大資料離線叢集遷移實戰

圖 3.6 Hive表新老叢集資料一致性校驗方案

四、遷移過程中的問題總結

  • 使用 DistCp 同步 HDFS 資料時漏配引數(-p),導致 HDFS 檔案 owner 資訊不一致。
  • 使用 DistCp 同步 HDFS 資料時覆蓋了 HBase 的 clusterId,導致 Hbase 兩個叢集之間同步資料時發生問題。
  • 在遷移開始後,新叢集的 Hive 表透過 export import 表結構來建立,再使用 DistCp 同步表的資料。導致 Hive meta 資訊丟失了 totalSize 屬性,造成了 Spark SQL 由於讀取不到檔案大小資訊無法做 broadcast join,解決方案是在 DistCp 同步表資料之後,執行 Hive 命令 ANALYZE TABLE TABLE_NAME COMPUTE STATISTICS 來生成表相關屬性。
  • 遷移期間由於在夜間啟動了大量的 MapReduce 任務,進行 Hive 表資料比對,佔用太多離線叢集的計算資源,導致任務出現了延遲,最後將資料比對任務放在資源相對空閒的時間段。
  • 工作流之間存在迴圈依賴,導致雙跑-全部遷移的流程走不下去,所以數倉建設的規範很重要,解決方案就是要麼讓使用者對任務重新組織,來重構工作流的依賴關係,要麼兩個工作流雙跑後,一起全部遷移。
  • 遷移期間在部分下游已經全部遷移的情況下,上游出現了問題需要重刷所有下游,由於只操作了老 DP,導致新環境沒有重刷,使遷移到新環境的下游任務受到了影響。
  • MapReduce 和 Spark Jar 型別的任務無法透過程式碼來檢測生成的上下游依賴關係,導致這類任務只能由使用者自己來判斷,存在一定的風險,後續會要求使用者對這類任務也配上依賴的 Hive 表和產出的 Hive 表。

五、總結與展望

本次的大資料離線叢集跨機房遷移工作,時間跨度近6個月(包括4個月的準備工作和2個月的遷移),涉及PB+的資料量和4萬日均排程任務。雖然整個過程比較複雜(體現在涉及的元件眾多、任務種類和實現複雜、時間跨度長和參與人員眾多),但透過前期的充分調研和探討、中期的良好遷移工具設計、後期的可控推進和問題修復,我們做到了整體比較平穩的推進和落地。同時針對遷移過程中遇到的問題,在後續的類似工作中我們可以做的更好:
  • 做好平臺的治理,比如程式碼不能對當前環境配置有耦合
  • 完善遷移工具,儘量讓上層使用者無感知
  • 單 Hadoop 叢集方案的能力儲備,主要解決跨機房頻寬的受控使用

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31545816/viewspace-2707957/,如需轉載,請註明出處,否則將追究法律責任。

相關文章