search
尋找貓咪~QQ 地點 桃園市桃園區 Taoyuan , Taoyuan

行進中換輪胎:萬字長文解析美團和大眾點評兩大數據平台是怎麼融合的

本文根據作者在 2017 年 ArchSummit 的分享記錄整理而成。

背景

互聯網格局複雜多變,大規模的企業合併重組不時發生。原來完全獨立甚至相互競爭的兩家公司,有著獨立的技術體系、平台和團隊,如何整合,技術和管理上的難度都很大。2015 年 10 月,美團與大眾點評合併為今天的「美團點評」,成為全球規模最大的生活服務平台。主要分佈在北京和上海兩地的兩支技術團隊和兩套技術平台,為業界提供了一個很好的整合案例。

本文將重點講述數據平台融合項目的實踐思路和經驗,並深入地討論 Hadoop 多機房架構的一種實現方案,以及大面積 SQL 任務重構的一種平滑化方法。最後介紹這種複雜的平台系統如何保證平穩平滑地融合。

兩家公司融合之後,從業務層面上,公司希望能做到「1+1>2」,所以決定將美團和大眾點評兩個 App 的入口同時保留,分別做出各自的特色,但業務要跨團隊劃分,形成真正的合力。比如麗人、親子、結婚和休閑娛樂等綜合業務以及廣告、評價 UGC 等,都集中到上海團隊;而餐飲、酒店旅遊等業務集中到北京團隊。為了支撐這種整合,後台服務和底層平台也必須相應融合。

點評 App 和美團 App 的數據,原來會分別打到上海和北京兩地的機房,業務整合之後,數據的生產地和數據分析的使用地可能是不一樣的。同時,隨著公司的融合,我們跨團隊、跨業務線的分析會越來越多,並且還需要一些常態化的集團級報表,包括流量的分析表、交易的數據表,而這些在原來都是獨立的。

舉個例子,原點評側的分析師想要分析最近一年訪問過美團和大眾點評兩個 App 的重合用戶數,他需要經過這樣一系列的過程:如下圖所示,首先他要想辦法找到數據,這樣就需要學習原美團側數據平台元數據的服務是怎麼用的,然後在元數據服務上去找到數據,才能開始做分析。

而做分析其實是一個人工去做 SQL 分解的過程,他需要把原點評側的去重購買用戶數拉下來,然後發到原美團側的數據平台,這個環節需要經歷一系列的操作,包括申請賬號、下載數據、上傳數據,可能還會踩到各種上傳數據限制的坑等等。最終,如果在這些都走完之後想做一個定期報表,那他可能每天都要去人工處理一回。如果他的分析條件變了怎麼辦?可能還要再重新走一遍這個流程。

所以他們特別痛苦,最終的結果是,分析師說:「算了,我們不做明細分析了,我們做個抽樣分析吧!」最後他做了一個在 Excel 里就能做的去重數據量的分析。我們作為平台開發的同學來說,看到這個事情是非常羞愧的。那怎麼辦呢?

在經過一些磨合后,我們得出一個結論,就是必須進行數據口整合。

融合實踐

確立目標

我們定了一個整體的目標,希望最終是能做到一個集群、一套數據平台的工具、一套開發規範。但是這個目標有點大,怎麼把它變的可控起來呢?首先至少看來是一個集群,也就是說從用戶訪問的角度上來講,他通過一個 Client 或一套用戶視圖就能訪問。工具方面至少明確已有的兩套,哪些是新的員工進來之後還需要學,哪些是未來會拋棄掉的。最終,讓大家認同我們有了一套數據平台規範,雖然這套規範短期內還沒有辦法做到完美。我們做的這些權衡其實是為了從整體上能將問題收斂。

但即使我們把這個目標縮小了,想要達到也是很難的。難點在哪呢?

難點

架構複雜,基礎設施限制

如上圖所示,整個數據平台基本上分為數據接入、數據開發、數據分析、數據輸出等等幾個階段。我這裡只列了其中涉及到跨機房、跨地域的部分,還有很多數據平台產品的融合,在這裡就不贅述了。在兩個公司融合之前,原點評側和美團側都已經在同地域進行多機房的部署了,也都很"默契"地抽象出了離線的機房是相對獨立的。在線的業務機房不管是通過消息隊列還是原點評自己當時做的 Blackhole(一個類似 DataX 的產品),都會有一系列數據收集的過程、對應任務的調度系統和對應的開發工具,也會有一些不在數據開發體系內的、裸的開源客戶端的跳板機。雖然架構大體一致,但是融合項目會牽扯整套系統,同時我們有物理上的限制,就是當時跨機房帶寬只有 10Gb。

可靠性要求

由於團購網站競爭激烈,兩家公司對於用數據去優化線上的一些運營策略以控制運營成本,以及用數據指導銷售團隊的管理與支撐等場景,都有極強的數據驅動意識,管理層對於數據質量的要求是特別高的。我們每天從零點開始進行按天的數據生產,工作日 9 點,老闆們就坐在一起去開會,要看到昨天剛剛發生過什麼、昨天的運營數據怎麼樣、昨天的銷售數據怎麼樣、昨天的流量數據怎麼樣;工作日 10 點,分析師們開始寫臨時查詢,寫 SQL 去查數據,包括使用 Presto、Hive,一直到 22 點;同時數據科學家開始去調模型。如果我們集群不能 work,幾千人每天的工作就只能坐在電腦面前看著 Excel……

當時的分析是這樣,如果考慮回滾的情況下,我們運維的時間窗口在平日只有一個小時,而且要對全公司所有用數據的同學進行通告,這一個小時就是他們下班之後,晚上 6 點至 7 點的時候開始,做一個小時,如果一個小時搞不定,回滾還有一個小時。周末的話好一點,可以做 4 小時之內,然後做全面的通告,相當於整個周末大家都沒法加班了,他們是非常不開心的。

體量

雖然沒有到 BAT 幾萬台節點的規模,但是也不算小了,融合時原點評的節點數是 500 個,數據量是 11 個 P;原美團的節點數是 3000 個,現在整體已經上 6000 了。這裡有一個比較關鍵的數據就是每天生成的數據量,由於我們的集群上面以數倉的場景為主,會有很多重新計算,比如說我要看去年每月的去重,這些都是經過一些時間變化之後會進行重算的。它對於分析數據的迭代速度要求很高,我每天可能都會有新的需求,如果原來的數據表裡面要加一個欄位,這個欄位是一個新的統計指標,這個時候我就要看歷史上所有的數據,就得把這些數據重新跑一遍。這裡的生成數據量其中有 50% 是對歷史的替換,50% 是今天新增的。這對於後面我們拷數據、挪數據是比較大的挑戰。

平台化與複雜度

兩家公司其實都已經慢慢變成一個平台,也就是說數據平台團隊是平台化的,沒法對數據的結果分析負責,數據平台團隊其實對外暴露了數據表和計算任務這兩種概念。平台化以後,這些數據表的 owner 和這些數據任務的 owner 都是業務線的同學們,我們對他們的掌控力其實是非常差的。我們想要改一個表的內容、一個數據任務的邏輯,都是不被允許的,都必須是由業務側的同學們來做。兩側的平台融合難免存在功能性的差異,數據開發平台的日活躍就有 100 和 240,如果查詢就是每天作分析的日活躍的話,原點評和美團加起來有 1000 多。所以在平台融合過程中,能讓這麼多用戶覺得毫無違和感是非常有挑戰的。

綜上,我們做了一個項目拆解。

項目拆解

數據互訪打通

數據互訪打通其實是最早開始的,早在公司宣布融合以後,我們兩側平台團隊坐在一起討論先做什麼,當時做了一個投入產出比的權衡,首要任務是用相對少的開發,先保障兩邊分析師至少有能在我們平台上進行分析的能力。接著是讓用戶可以去配置一些定時任務,通過配置一些數據拷貝任務把兩地數據關聯起來。

在這方面我們總共做了三件事。

原始層數據收集

在原美團側把原點評側線上業務機房一些 DB 數據以及 Server 的 log 數據同步過來。這個時候流式數據是雙跑的,已經可以提供兩邊數據合在一起的分析能力了。

集群數據互拷

集群數據互拷,也就是 DistCp。這裡稍微有一點挑戰的是兩邊的調度系統分別開了介面,去做互相回調。如果我們有一份數據,我想它 ready 之後就立即拷到另外一邊,比如原點評側有個表,我要等它 ready 了之後拷到原美團側,這個時候我需要在原美團側這邊配一個任務去依賴原點評側某一個任務的完成,就需要做調度系統的打通。本文主要討論大數據框架的部分,所以上面的調度系統還有開發平台的部分都是我們工具鏈團隊去做的,就不多說了,下文重點描述 DistCp。

其實 Hadoop 原生支持 DistCp,就是我起一個 MapReduce 在 A 集群,然後并行地去從 B 集群拖數據到 A 集群,就這麼簡單。只要你網路是通的,賬號能認(比如說你在 A 集群跑的任務賬號能被 B 集群認),並且有對應的讀許可權,執行端有計算資源,用開源版本的 DistCp 就可以搞定。

這方面我們做了一些權衡:

首先是因為涉及到帶寬把控的問題,所以同步任務是由平台團隊來統一管理,業務側的同學們提需求。

然後我們兩側集群分別建立一個用於同步的賬號,原則是在讀的那一端提交任務。什麼叫「讀的一端」?比如說我想把一個原點評側的數據同步到原美團側,原美團側就是要讀的那端,我在原美團側起這個任務去讀原點評側的數據,然後寫到原美團側。這裡的主要考慮是讀端更多是需求端,所以,他要在他的資源池裡去跑。另外,對集群的影響讀小於寫,我們希望對於被讀集群的影響能盡量減少。

當然,這都是一些臨時的項目,投入較小,但收益是磨合了兩地團隊。

Kerberos 跨域認證架構

接著介紹一下認證部分是怎麼打通的。原美團側和點評側恰好都用了 Kerberos 去做認證服務,這個 Kerberos 在這我不去詳細展開,只是簡單介紹一下。首先是 KDC 會擁有所有的 Client 和 Server,Client 就是 HDFS Client,Server 就是 Name Node,KDC 會有 Client 和 Server 的密鑰,然後 Client 和 Server 端都會保有自己的密鑰,這兩個甚至都是明文的。所有的密鑰都不在傳輸過程中參與,只拿這個密鑰來進行加密。基於你能把我用你知道的密鑰加密的信息解出來,這一假設去做認證。這也是 Kerberos 架構設計上比較安全的一點。

Kerberos 不細講了,下面詳細講一下 Kerberos 跨域認證架構。

一般公司都不會需要這個,只有像我們這種兩地原來是兩套集群的公司合併了才需要這種東西。我們當時做了一些調研,原來的認證過程是 Client 和 KDC 去發一個請求拿到對應 Server 的 ticket,然後去訪問 Server,就結束了。但是如上圖所示,在這裡它需要走 3 次,原來是請求 2 次。大前提是兩邊的 Kerberos 服務,KDC 其中的 TGS 部分,下面存儲的內容部分分別要有一個配置叫 krbtgt,它有 A realm 依賴 @ B realm 這樣的一個配置。

兩邊的 KDC 基於這個配置是要一致的,包括其中的密碼,甚至是包括其中的加密方式。那這個時候我們認為這兩個 KDC 之間實際上是相互信任的。

流程是 Client 發現要請求的 Server 是在另外一個域,然後需要先去跟 Client 所屬的 KDC 發請求,拿一個跨域的 ticket,就是上圖中 1 右邊那個回來的部分,他拿到了這個 krbtgt CREALM @ REALM。然後 Client 拿著跨域的 ticket 去請求對應它要訪問 Service 那一個域的 KDC,再去拿對應那個域的 Service 的 ticket,之後再去訪問這個 Service。這個流程上看文檔相對簡單,實則坑很多,下面就講一下這個。

上圖是 Kerberos 跨域認證的一些要求。

首先第一個比較大的要求就是密鑰的編碼一致,這有一個大坑,就是你必須讓兩個 KDC 拿到的信息是一樣的,它們基於這個信息去互信,去互相訪問。然後 krb5.conf 裡面有一些比較詭異的 domain_realm 策略,這個在你網路環境不一致的時候會有一定的影響,包括 DNS 也會影響這個。在你的網路環境比較不可知的時候,你需要做做測試,嘗試去怎麼配,然後在 Hadoop 端有兩個配置需要做,分別在 Server 端和 Client 端配置即可。其中比較噁心的是說,在測試的過程當中,需要去看 Hadoop 的詳細日誌,需要開一下它的 Debug,然後去看一下它真正請求的那個域是什麼樣的。因為我們翻代碼發現,Hadoop 底層有對 log,Client 去請求 realm 的隱改,就是說我認為我應該是這個 realm 啊,它為什麼傳出來的是另外一個 realm?這個是比較坑的一點。

我們做完這個項目之後,分析師就可以愉快地配置一些調度任務去同步數據,然後在對應的集群上去關聯他們的數據進行分析了。做完這個項目之後,我們兩邊的團隊也相互磨合,相互形成了一定的認可。因為這個小項目涉及到了數據平台的每一個領域,包括工具鏈、實時計算、離線的團隊都做了一些磨合。

集群融合

粗看起來,打通了數據平台,我們的大目標似乎已經完成了:一個集群、一套數據平台的工具、一套開發規範。把數據拷過來,然後重新改它的任務,就可以形成在統一的一套工具和規範裡面用一個集群,然後慢慢把原來團隊維護的服務都下掉就好了。事實上不是這樣的,這裡面有大量的坑。如果接下來我們什麼都不做的話,會發生什麼情況呢?

數據 RD 會需要在遷移的目標平台重建數據,比如說我們都定了,以後把原美團側平台砍掉,那麼好,以後都在原點評側的平台,包括平台的上傳工具、平台的集群去使用、去開發。這個時候,至少原美團側的同學會說:「原點評那邊平台的那些概念、流程,可能都跟我不一樣啊,我還需要有學習的時間,這都還好」。但他們怎麼遷移數據呢?只能從源頭開始遷移,因為對端什麼都沒有,所以要先做數據的拷貝,把上游所有的表都拷貝過去。然後一層一層地去改,一整套任務都要完全重新構建一遍。

那我們有多少任務呢?

我們當時有 7000 個以上,後來超過 8000 個任務,然後我們平均深度有 10 層。也就是說上游先遷過來,然後下游才能遷。整個流程會變成數據表的拷貝,然後上線任務進行雙跑。因為必須得有數據的校驗,我才能放心地切過來,花的時間大概是拷貝數據 1~4 天,然後改代碼加測試再加雙跑,可能要 3~5 天。這裡我們有一個流水線的問題,如上圖所示,藍色的部分只有一層依賴的,當然我把這個左邊的 ODS 都遷完了之後,1 層依賴的 Task 1、Task 2、Task 3、Task 8 中,Task 1、2、3 就可以遷了,但是 Task 8 還是不能遷的,因為 Task 8 依賴的 Task 7 還沒過來。我再走一層,Task 4 的負責人要等上游相關任務都遷完了之後才能幹活,那整個這個遷移就純線性化,我們大概估了一下,并行度不會超過 50。如果是兩地兩份數據,這個項目的周期會變成特別長,會有長期的兩份數據、兩份任務。這個時候,第一是我們真存的下嗎?第二是如果我要遷移出來那個方向的業務有需求的變更,我怎麼改?我要兩邊都再改一遍?所以這個是非常不可控的。

那這個時候怎麼辦?

集群融合的問題本質

反思一下這個問題的本質,首先我們是不能雙跑的,因為一旦雙跑,我們必須有常態化的兩份數據,然後衍生一系列的校驗、存儲量、切換策略等問題。所以我們必須得有一套數據,一套任務執行機制。後續任務的改變,不管是替換工具鏈上的東西,替換計算引擎,比如說讓兩邊 Hive、Spark 和 UDF 去做一致化的時候,其實本質上是說對單個任務的修改,對每個任務灰度的修改就好了。

所以我們推斷出,必須自底向上地去進行融合,先合集群,然後後續再推動上游平台和引擎的融合。

集群融合的解決思路

整體我們融合的思路是這樣的,集群融合先行,兩邊的 Hadoop 的服務架構和代碼先進行統一,其次拷貝原點評側集群的 Block,同步到原美團側機房的兩個副本。這裡有一個大的前提,第一個是原點評側的集群節點數相對來講確實小,再一個就是原點評側的機房確實放不下了,它當時只能擴容到 10 月,再往後擴就裝不下機器了。

所以我們將原點評側的集群,合併到原美團側機房,然後進行拷貝和切換。我們讓整個這個集群變成在原美團側機房一樣的樣子,然後進行融合。我們會把上面的客戶端和元數據統一,使得訪問任何一個集群的時候,都可以用一套客戶端來做。一旦我們做到這個樣子之後,基於統一的數據、集群的元數據和訪問入口之後,我們上面的工具鏈就可以慢慢地去做一個一個機制,一個一個模塊的融合了。

簡單總結下來就是四步:統一、拷貝、切換、融合,下面我們來展開說一下這四步。

統一

第一優先順序要解決的是上圖中標紅的部分,兩邊的 Hadoop 版本是不一樣的,我們需要將原上海側的版本變成我們的 2.7.1 帶著跨機房架構的版本。同時因為我們後面要持續地去折騰 Hadoop 集群,所以必須先把原上海側的 HDFS 架構改全,改成高可用的。

這裡有一個小經驗就是,我們自研的 patch 對改的 bug 或者是加的 feature,一定要有一個機制能夠管理起來,我們內部是用 Git 去管理的,然後我們自研的部分會有特殊的標籤,能一下拉出來。我們當時其實互相 review 了上百個 patch,因為當時兩個團隊都有對集群,包括 Hive 等等這些開源軟體的修改。這是統一的階段,相對容易,就是一個梳理和上線的過程。接下來是拷貝的階段。

拷貝

上圖是最終的效果圖,同步在運行的打通任務還是用 DistCp,然後先把原點評側的 HDFS 跨機房部署。但是這個時候原點評側的 YARN 還是在上海機房。在這個過程當中,因為 HDFS 跨機房部署了,所以原新上線的 DataNode 可以承載更多在原點評側集群的冷數據。這個過程是慢慢進行拷貝的,大概持續了 4 個月,中間長期都是 10Gbps 的小管子。

這個相當於把原點評側的 NameNode(這個時候還沒有徹底下線)切換到原美團側機房,然後把對應的 YARN 重新啟動起來。這裡有一個小 trick 就是原美團側機房的承載能力,大概是 1000 多台節點,是原點評側的兩倍,所以我們才能做這個事,最近我們剛剛把上海機房的節點遷完。

那整個集群的拷貝和切換是怎麼做的呢?其實就是用我們自研的一套 Hadoop 多機房架構。可能做 Hadoop 集群維護管理的同學們對這個有深刻的體會,就是不時地就要從一個機房搬到另一個機房。設計目標是說我們一個 Hadoop 集群可以跨機房去部署,然後在塊的力度上能控制數據副本的放置策略,甚至是進行主動遷移。

設計是怎麼做的呢?整個 Hadoop 原生的架構其實沒有機房這個概念,只支持 Rack 也就是機架,所有伺服器都被認為是在同一個機房的。這個時候不可避免地就會有很多跨機房的流量,就如果你真的什麼都不幹,就把 Hadoop 跨機房去部署的話,那麼不好意思,你中間有好多的調用和帶寬都會往這兒走,最大的瓶頸是中間機房網路帶寬的資源受限。

我們梳理了一下跨機房部署的時候大概都有哪些場景會真正引發跨機房流量,基本上就這 3~4 個。首先是寫數據的時候,大家知道會 3 副本,3 個 DataNode 去建 pipeline,這個時候由於是機器和機器之間建連接,然後發數據的,如果我要分機房部署的話,肯定會跨機房。那我要怎麼應對呢?我們在 NameNode 專門增加 zone 的概念,相當於在 Rack 上面又加了一層概念,簡單改了一些代碼。然後修改了一下 NameNode 邏輯。當它去建立 pipeline 的時候,在那個調用裡面 hack 了一下。建 pipeline 的時候,我只允許你選當前這個 Client 所屬的 zone,這樣寫數據時就不會跨機房了。

這些 Application 在調度的時候有可能會在兩個機房上,比如說 mapper 在 A 機房,reducer 在 B 機房,那麼中間的帶寬會非常大。我們怎麼做的呢?在 YARN 的隊列裡面,也增加 zone 的概念,我們用的是 Fair Scheduler。在隊列配置裡面,對於每一個葉子隊列,都增加了一個 zone 的概念。一個葉子隊列,其實就是對應了這個葉子隊列下面的所有任務,它在分配資源的時候就只能拿到這個 zone 的節點。讀取數據的時候有可能是跨機房的,那這個時候沒有辦法,我們只有在讀取塊選擇的時候本地優先。我們有一些跨機房提交 job 的情況,提交 job 的時候會把一些 job 裡面的數據進行上傳,這個時候加了一些任務的臨時文件上傳的是任務所在的目標機房。這裡做一些簡單的改動,最重要的是提供了一個功能,就是我們在拷貝數據的時候,其實用 balancer 所用的那一套介面,我們在此基礎之上做了一層 Hack,一層封裝。形成了一個工具,我們叫 ZoneTransfer,又由它來按照我們一系列的策略配置去驅動 DataNode 之間的跨機房的 block 粒度的拷貝。

上圖是我們跨機房架構的架構圖,下面的 Slave 裡面有 DN(DataNode) 和 NM(NodeManager),上面跑的同顏色的是一個 App。我們在 RM(ResourceManager) 裡面的葉子隊列里配置了 zone 的概念,然後在調度的時候如大家所見,一個 App 只會在一個機房。然後下面黑色的線條都是寫數據流程,DN 之間建立的 pipeline 也會在一個機房,只有通過 root 去做的,DN 之間做數據 transfer 的時候才會跨機房進行,這裡我們基本上都卡住了這個跨機房的帶寬,它會使用多少都是在我們掌控之內的。

在上線和應用這個多機房架構的時候,我們有一些應用經驗。

首先在遷移的過程當中我們需要評估一點就是帶寬到底用多少,或者說到底多長時間之內能完成這個整體數據的拷貝。這裡需要面對的一個現實就是,我們有很多數據是會被持續更新的。比如我昨天看到這個塊還在呢,今天可能由於更新被刪,那昨天已經同步過來的數據就白費了。

那我昨天已經同步過來的數據就白費了。所以我們定義了一個概念叫拷貝留存率。經過 4 個月的整體拷貝,拷貝留存率大概是 70% 多,也就是說我們只有 70% 的帶寬是有效的,剩下的 30% 拷過去的數據,後面都被刪了。

第二個是我們必須得有元數據的分析能力,比如說有一個方法能抓到每一個塊,我要拷的塊當前分佈是什麼樣子。我們最開始是用 RPC 直接裸抓 Active NameNode,其實對線上的影響還是蠻大的。後面變成了我們通過 FsImage 去拉文件的列表,形成文件和塊的列表,然後再到把請求發到 standby,那邊開了一個小口子,允許它去讀。因為 FsImage 裡面是沒有 block 在哪一個 DataNode 的元信息的。

這裡需要注意的一點就是,我們每天都會有一個按天的數據生產,為了保證它的一致性,必須在當天完成。在切換之前,讓被切換集群的 NN(NameNode)進入 SafeMode 的狀態,然後就不允許寫了,所有的寫請求停止,所有的任務停止。我們當時上線大概花了 5~6 個小時吧,先停,然後再去拷貝數據,把當天的所有新生產的數據都拷過來,然後再去做操作。這裡最基本的要做到一點就是,我們離線的大數據帶寬不能跟線上的服務的帶寬搶資源,所以一定要跟基礎設施團隊去商量,讓他們做一些基於打標籤的帶寬隔離策略。

融合

當我們把集群搬到了原美團側的機房之後,又做了一層融合。想讓它看起來像一個集群的樣子,基本上只需要 3 步。首先是「把冰箱門打開」,把原點評側集群的那個 NN 作為一個 federation 合到原美團側的集群,只需要改 cluster ID,去客戶端改 mount table 配置,cluster ID 是在元數據裡面。第二個是對 Hive 進行元數據的融合。我們恰好兩側元數據存儲都是用 MySQL 的,把對應的表導出來,灌到這邊,然後持續建一個同步的 pipeline。它是長期活動的,到時候把上傳的服務一切就可以。

前面說的那個做了跨域認證的配置我們還是要拆掉的,必須進行服務認證的統一,不然的話以後沒法看起來像一個集群,這個時候把原來的 KDC 裡面的賬號進行導出,之後逐步地去切換每一個配置,讓它慢慢切到新的 KDC。切的過程當中,我們各種請求還是有跨域情況的,我們認為兩個域是一體的,是一樣的。等切乾淨之後,也就是原來的 KDC 沒有請求了之後,我們再把它幹掉。

開發工具融合

集群融合結束后,我們就做了開發工具的融合。由於這個跟大數據基礎架構這個主題關係不是特別大,開發工具都是我們內部自研的,涉及的程序也很複雜,是一個特別大的項目,涉及一系列複雜的工具,每個模塊的融合、打通。所以這個暫時不講了。另外我覺得比較有意思的是下面這一點,就是原點評側的一個拆庫,這個在很多公司的數據平台慢慢擴大的過程當中可能會用到。

原點評側拆庫

難點

先說一下背景,由於原點評和原美團整體歷史上發展經驗、周期和階段不同,如上圖所示,原點評側的數據倉庫是先有的 Hadoop 集群,後有的數據倉庫平台,因此有很多平台完全沒法掌控的私有庫,但是他們對於數倉所在庫的掌控是非常強的,所有的任務都在這一個大的 Hive 庫裡面,裡面有七八千張表。而原美團側是先有的數據平台,後來因為數據平台整個體量撐不住了,底層改成了 Hadoop。同時在平台化的演進過程中,已經慢慢把各個業務進行獨立拆分了,每個業務都有一個獨立的私有庫,簡單來說就是庫名和庫名的規範不一樣。我們希望能讓這兩套規範進行統一。

我們如何去做呢?

原來任務的內容大概是 insert into 一個 BI 庫裡面的一張表,接著 select from BI 庫裡面的某兩張表,然後 where group by。像這樣的任務我們有七八千個,它們在我們平台上配置著每天的依賴調度。我們希望把它都改成下圖中的樣子。所有涉及到的這些表都需要改名字,說白了就是一個批量改名字的事兒。

改名字聽起來很簡單,實際上並不是,我們有近 8000 個這樣的任務需要改,同時這些任務相互之間都有非常複雜的依賴。下圖是我隨便找的一個,原美團側某一個任務所有上游和下游的依賴關係圖,如此複雜,任務的平均深度大概有 10 層,這還是平均數,最嚴重的可能要有大幾十層。如果我們改這裡面的任務表達,就只能分層推動。但是,當我們每改其中一個的時候,可能上下游都得跟著改,具體是什麼樣子的呢?

下圖是我們的原始結構,首先這裡有一個大前提是每一個任務只對一個結果表。原始的結構中,a 表只依賴 o1 表,b 表依賴 o1、o2,然後 c 表只依賴 o2,它們之間相互關聯。這時候我希望可以對庫名和表名進行一次性的修改。那如果我們逐層地去改寫怎麼辦呢?首先要先把最上層的 mart 表改了,而我一旦改上游的某一個表,所有跟對它有依賴的表都必須改任務內容。每推動一層改動,下面一層都要變動多次,這樣一來,我們這個流程就非常受限。

剛剛那個情況基本上是類似的,就是說我們對它們的改動沒法批量化、信息化、流水線化,所有的用戶和數據開發們,需要跟我們去聊,最近改了多少,然後誰誰誰沒改完,誰誰誰又說要依賴他,整個依賴圖是非常大的,我們整個項目又不可控了。那怎麼辦呢?

解決方案

很簡單,我們只幹了一件事情,就是在 Hive 層面上進行了一波 Hack。比如說我要讓原來叫 bi.o2 的表未來會變成 mart_b.o2,我就同時允許你以 mart_b.o2 和 bi.o2 這兩種方式去訪問 bi.o2 這張表就好了。不管是寫入還是讀取,我們只需要在 Hive 的元數據層面去做一層 Hack,然後做一個對應表,這個對應表我們是有規範的、能梳理出來的。在這之後,任何一個人都可以把他的任務改寫成他希望的樣子而不受任何影響,他寫的那些表還是原來的那些表,真正在物理上的存在還是 bi. 什麼什麼這樣的表,我們整個項目就 run 起來了。

具體的實施流程是這樣,首先先梳理業務,確定整體的映射關係。然後 Hive 元數據入口上去做別名能力,我們是在 Hive metaserver 裡面去改的,大部分請求都在這裡面,包括 Spark 的、Presto 的、Hive 的等,都能兼容掉,推動分批次改寫,單任務內以及任務鏈條內完全不需要做依賴關係的約束,最終真正實現的是自動化地把 SQL 文本替換掉了。業務的同學們只需要批量看一個檢測報告,比如說數據對應上有沒有什麼問題,然後一鍵就切了。

我們用了一個季度業務側來磨合、嘗試練習和熟練,同時做工具的開發。然後第二個季度結束后,我們就完成了 7000 多個任務中 90%SQL 任務批量的改寫。當任務都切完了之後,我們還有手段,因為所有的請求都是從 Hive 的 metaserver 去訪問的,當你還有原有的訪問模式的時候,我就可以找到你,你是哪一個任務來的,然後你什麼東西改沒改,改完了之後我們可以去進行物理上的真正切分,幹掉這種元數據對應關係。

物理上的真正切分其實就是把原來都統一的庫,按照配置去散到真實的物理上對應的庫上,本質還是改 NN 一個事情。

總結與展望

未來——常態化多機房方案

我們目前正在做的一個項目,就是常態化地把集群跨機房去跑,其中最核心的就是我們需要對跨機房的數據進行非常強的管理能力,本質上是一個 Block 粒度 Cache 的事情,比如說 Cache 的擊穿、Cache 的預熱或者 Cache 的等待等等,都是一個 Cache 管理的事情。我們會引入一個新的 server,叫 zone Server,所有的 Client 請求,NameNode 進行塊分佈的時候,調整和修改。之後大家會在美團點評技術博客上看到我們的方案。

反思——技術換運營

數據平台做起來是很痛苦的,痛苦在哪兒呢?第一,數據平台對上層提供的不只是 RPC 介面,它要管的是數據表和計算任務。所以我們做 SLA 很難,但是我們還在努力去做。第二,就是最開始的時候一定是基於開源系統拼接出來的,然後再到平台化,這一定是一個規範的收斂,也是限制增多的過程。在這個過程中,我們必須去推動上面應用的、不符合規範的部分,推動他們去符合新的規範。平台的變更即使做到兼容,我們的整體收尾還是要儘快掃清的,不然整個平台就會出現同時進行大量灰度、每一個模塊當前都有多種狀態的情況,這是不可維護的。

綜上,我們定義了一個概念叫「可運營性」,推動用戶去做遷移、做改動是一個"運營的事情"。可運營性基本上的要求如下。

  • 可灰度。任務的改動是可灰度的。

  • 可關門。當某一刻,我不允許你再新增不符合新規範的任務、表或者配置,我們內部叫「關門打狗」,就是說先把新增的部分限制住,然後再去慢慢清理老的。

  • 進度可知。清理老的我們需要有一個進度可知,需要有手段去抓到還有哪些任務不符合我們新的規範。

  • 分工可知。抓到任務的分工是誰,推動相關團隊去改動。

  • 變更兼容 / 替代方案。我們肯定過程中會遇到一些人說:不行,我改不動了,你 deadline 太早了,我搞不定。這時候得有一些降級或者兼容變更的一些方案。

那我們什麼時候去使用技術降低運營成本呢?前面已經有兩個例子,就集群的遷移和融合,還有 Hive 表別名去幫助他們改任務名,這都是用技術手段去降低運營成本的。

怎麼做到呢?

第一是找核心問題,我們能否徹底規避運營、能不能自動化?在集群融合的過程當中,其實已經徹底避免了運營的問題,用戶根本都不需要感知,相當於在這一層面都抽象掉了。第二,是即使我沒法規避,那我能不能讓運營變得批量化、并行化、流水線化、自動化?然後當你抓核心問題有了一個方案之後,就小範圍去迭代、去測試。最後還有一點,引入架構變更的複雜度最終要能清理掉,新增的臨時功能最後是可被下線的。

體會——複雜系統重構與融合

最後稍微聊一下複雜系統的重構與融合。從項目管理的角度上來講,怎麼去管控?複雜系統的重構還有融合本質上最大的挑戰其實是一個複雜度管理的事情,我們不可能不出問題,關鍵是出問題后,對影響的範圍可控。

從兩個層面去拆分,第一個層面是,先明確定義目標,這個目標是能拆到一個獨立團隊里去做的,比如說我們最開始那四個大的目標,這樣保證團隊間能并行地進行推動,其實是一點流水線的思路。第二,我們在團隊內進行目標的拆分,拆分就相對清晰了,先確定我要變更什麼,然後內部 brainstorming,翻代碼去查找、測試、分析到底會對什麼東西產生影響,然後去改動、測試、制定上線計劃。

內部要制定明確的上線流程,我記得當時在做的時候從 11 月到 12 月我們拆分了應該是有 11 次上線,基本上每次大的上線都是在周末做的,10、11、12 月總共有 12 個周末,一共上線 11 次,大的上線應該是佔了 7 到 8 個周末吧。要提前準備好如何管理依賴,如何串列化,然後準備上線,上線完怎麼管理,這些都是在整個項目管理過程當中需要考慮的。

其中,兩個可能大家都持續提的東西,第一個是監控,要知道改完了之後發生了什麼,在改的時候就像加測試用例一樣把改動部分的監控加好。第二要有抓手,如果我線上垮了,這個時候重複恢復的成本太高,也就是完全重啟、完全回滾的成本太高,我能不能線上進行一些改動?

最後這張圖,獻給大家,希望大家在對自己系統改動的時候,都能像這哥們一樣從容。

本文系美團點評技術團隊原創文章,已經授權 InfoQ 公眾號轉發傳播。

開源 Cruise Control:LinkedIn 1800 台 Kafka 伺服器集群的自動化運維利器

又到了秋季跳槽季,BAT 開發部又在大力招大數據工程師了!想進 BAT,但擔心自己能力不足,怎麼辦?StuQ 幫你搞定!這個開學季,StuQ 送你價值 3000 元的 BAT 「名師系列課」。來自大數據 / 前端 / 運維領域的一線名師,帶你學習一線互聯網公司技術團隊的實戰經驗,讓你掌握團隊項目中遇到問題的處理和解決方案,提升自己及團隊的研發能力,助你進階 BAT。趕緊點「 閱讀原文 」,註冊學習去~



熱門推薦

本文由 yidianzixun 提供 原文連結

寵物協尋 相信 終究能找到回家的路
寫了7763篇文章,獲得2次喜歡
留言回覆
回覆
精彩推薦