1. 程式人生 > >餓了麼大資料平臺建設

餓了麼大資料平臺建設

【導語】隨著接入的需求方越來越多樣化,對大資料的資料使用、資料儲存與計算的需求也越來越多樣化,同時業務飛速發展,叢集的規模也急速擴大。如何在這樣的場景下通過大資料平臺,穩定支撐住業務的發展是一個不小的挑戰。本文分享主要平臺工具鏈,技術、選型及架構設計上的一點經驗。

大資料平臺現狀

餓了麼的大資料平臺團隊成立於2015年5月份左右,在16年4月份,Hadoop叢集規模還只在100+節點數,而在一年時間裡叢集規模快速增長到1000+的水平,這還是在引入資料生命週期進行管控的情況下的規模增速;同樣,流計算叢集的規模雖然相對較小,但也經歷了10倍的增長,一些topic的吞吐量已超過百萬每秒。
當前平臺部分的邏輯架構如圖1,並持續演進。

圖1  餓了麼大資料平臺的邏輯架構圖
圖1 餓了麼大資料平臺的邏輯架構圖

當初面臨的問題

餓了麼已經成立9年時間,相對而言資料平臺團隊非常年輕,在加入團隊之初面臨瞭如下挑戰:

  • 人少活多 積累不足
  • 內在質量 “差不多就行”
  • 故障處理 “千人千面”

因此,主要以效率、質量和持續擴充套件為核心來建設資料平臺。

技術選型

如圖2所示,大資料的技術棧非常多樣化,對於團隊很多初入大資料領域的成員來說很容易在嘗新過程中消耗團隊的生產力,因此在加入團隊初期,首先就要確定在當時條件下的技術選型。

圖2  多樣化的大資料技術棧
圖2 多樣化的大資料技術棧

選型原則

在技術選型方面堅持的原則是“3T”:要解決什麼樣的問題和場景(Trouble),有哪些技術可供選擇(Technology),以及團隊技術棧與目標採用技術的匹配程度或者說掌控能力(Team)。

下面舉幾例子來看:

即席查詢引擎選型

在以Hive on Hadoop為中心的離線資料倉庫,最開始分析師以及資料工程師也都是使用Hive來做資料分析和探索,但是Hive本質上是基於MapReduce架構的,並不是很適合這個場景。當時所選擇的目標集中在Presto和SparkSQL上,社群活躍度Spark是最高的,並且從SQL語法相容性來看SparkSQL也是最合適的,使用者的使用成本比較低,但是在測試的時候發現失敗率高達50%,在相容性和穩定性方面如果無法對Spark程式碼做一定定製化開發的話達不到我們的要求,相對而言Presto雖然語法相容性不如SparkSQL,但是比較穩定並且在執行效率上也高於SparkSQL,考慮到當時團隊的Spark力量積累不足,同時團隊成員也有曾使用和管理過Presto的經驗,因此優先考慮Presto作為Ad-hoc的查詢引擎。

架構設計

技術選型確定了,接下來需要解決在業務急速增長情況下的架構設計問題。理想的架構是系統上線後儘量減少人的參與,或通過簡單的流程即可應對外部變化,追求可持續擴充套件的架構設計,這裡通過一個具體案例來表達我們在設計時的關注點。

如圖5,流入三個源資料流:使用者行為、主站訂單、以及開放平臺訂單的訂單渠道,進行各種實時指標的計算,其中分渠道訂單相關指標的計算和多維度組合下的UV計算場景是比較典型的流計算問題。

 圖5  流入三個源資料流的UV計算渠道訂單
圖5 流入三個源資料流的UV計算渠道訂單

非同步

分渠道訂單指標計算需要將主站訂單流和開發平臺訂單流進行Join計算,因為是多資料流的合併計算,所以在設計該架構時基於的假設是:不同源資料流之間的到達時間無法協同,我們將問題轉化為”在可調整的時間視窗內通過匹配觸發Join計算”。具體落地則是通過Redis快取住還沒有匹配的訂單資料,引入時間視窗是為了控制住快取的大小,而時間視窗的控制有兩處:在拿到資料時會檢查是否在時間視窗內;另外在未匹配的情況下寫入Redis時會把時間視窗通過TTL的方式一併維護,避免多餘的維護任務。

可擴充套件性

UV計算首先要解決的就是去重問題,比如判斷某個deviceID是否是當天的平臺新訪客,一種做法是通過Redis的集合來判斷,具體資料結構如下:

key : YYYYMMDD_uv
value : deviceID的集合

這樣的設計會帶來熱點問題,所有該維度的deviceID請求都會打到一個節點上產生熱點,當流量增加時無法通過直接擴容來解決問題,那麼自然就想到如下的資料結構:

key : _YYYYMMDD
value : 佔位符

通過如此轉化可以很好地把請求打散,有具更好的擴充套件性。

回到多維度UV計算的場景下,通常涉及到的組合維度可以達到2的N次方,如果採用上述結構無論是讀寫的吞吐還是空間的消耗都是巨大的,擴充套件成本非常高,我們選擇犧牲一定精度來達到低成本的擴充套件性。UV計算本質是基數估計問題,在該領域非常出名的資料結構就是HyperLogLog(以下簡稱HLL),雖然Redis本身支援HLL但是無法避免熱點問題,我們選擇在流計算過程中本地計算HLL,因為HLL支援merge操作同時冪等可回放,大量的計算都在計算任務節點本地完成,無論是shuffle還是落地儲存的處理毫無壓力,通過壓測,在不擴容的情況下可以支撐20倍的壓力。

穩定性

對於穩定性主要通過事前、事中和事後三個方面來看,即執行計劃、故障處理和事後覆盤。

執行計劃

首先線上變更為了控制風險,有兩點是必須遵守的:一定要有可行的回滾方案,一定要灰度。

其次,對於具體的尚未自動化支援的變更流程或SOP需要考慮異常分支,大多數看到的SOP文件只是考慮正常流程一步步執行下來,可是經常遇到的問題反而是某個流程走不通或者出問題了。

最後,就是變更時間估算很重要,對變更的節奏把握的越清楚風險越從容。

故障處理

對於故障處理我們比較關注的一個指標就是MTTR(Mean Time To Recovery,即平均恢復時間)。

  • 故障恢復時間=告警響應時間+介入處理時間

從上面的公式可以看出MTTR主要是由響應時間和處理時間構成。

監控 ≠ 告警

對於穩定性來說監控是底線,但是”監”而無”控”的現象非常普遍,帶來的結果是收到一個告警不知道如何處理,或者忽略掉,或者“千人千面”處理,問題不同程度地被隱藏或放大。

監控 = metrics+trigger+action

那麼如何“控”呢?

監控的”控”

我們堅持如下次序:低成本的自愈優先於流程或SOP,如果SOP沒有覆蓋的場景就需要一個原則來指導方向,比如故障發生後是優先保哪個方面,一致性還是可用性。逐步迭代將故障處理的“千人千面”收斂到從容有序。

覆盤原則

故障覆盤對於系統穩定性的提高是個非常非常有價值的閉環反饋,在這方面我們實踐著Facebook的DREP原則,同時基於實踐經驗引入了W9(Workaround),強調可持續的穩定性。

圖6  Facebook的DREP原則
圖6 Facebook的DREP原則

工具鏈

上文提到的技術選型及架構設計和穩定性保障通常依賴於人,我們更希望將人的經驗構建在工具中,減少對人的依賴,提升組織的可擴充套件性。圖7為工具鏈的架構圖。

圖7  工具鏈架構圖
圖7 工具鏈架構圖

儘量擴大工具在整個資料工作生命週期的覆蓋度,為資料工作人員賦能,主要包括:

  • 元資料管理:指標管理,資料質量監控,血緣關係追溯等;
  • 許可權管理及資料安全:資料底層的安全,基礎設施許可權體系打通,以及資料使用安全;
  • 資料開發管理:資料表管理,資料探查,離線與實時資料開發和任務運營;
  • 資料應用:資料介面開發(SQL即介面),資料報表開發(SQL即報表)和管理;
  • 自動化運營:整個基礎設施的管理,包括CMDB、工作流引擎、容量規劃、效能分析與告警管控等。

本文著重分享資料開發管理和資料報表開發。

圖8  資料表管理系統功能示意圖
圖8 資料表管理系統功能示意圖

資料表管理

生產資料表是所有資料開發工作的源頭,因此我們把生產資料表的建立及維護工作統一收到資料表管理系統(以下稱dtmeta)中,除了建表的基礎功能外,主要關注如下資訊:

  • 靜態資料:表所屬主題,欄位是維度還是度量,是否敏感或加密欄位,表的生命週期和備份週期以及表的物理結構資訊等;
  • 動態資料:主要包含表的讀寫熱度情況,以及表的容量變化情況,便於針對性策略優化和問題分析。

有了這些資訊,減少了大量後續維護的工作,降低互動成本。

資料開發及任務管理系統

資料開發

  • 模板化:資料開發工作者可以直接在系統中開發ETL任務,支援動態變數,同時可配置觸發方式、期望完成時間等屬性,作為特徵提供給排程系統;
  • hook:在任務啟動前和執行結束後可以觸發的action,比如資料來源的延遲檢測,資料抽取後的資料校驗或者推送後臨時資料狀態的清理(觸發)等;
  • 依賴識別:對於基於依賴觸發的任務來說,依賴的自動化識別非常必要,人工配置依賴會遇到迴圈依賴以及依賴遺漏,從而影響任務的SLA甚至資料質量;
  • 多資料儲存推送 :Hive通過外部表的方式支援向ES、Redis、Cassandra、MongoDB等資料儲存的推送以及抽取,簡化資料開發過程中的資料交換工作。
圖9  Titan排程平臺編輯任務截圖示意
圖9 Titan排程平臺編輯任務截圖示意
圖10  Hive的多資料儲存推送
圖10 Hive的多資料儲存推送

任務執行與管理

對於任務執行和任務的自助化運營管理我們主要關注這幾點:

  • 壓力感知:會感任務執行的目標系統比如Yarn的壓力,達到反壓的效果而不是持續將任務直接提交給目標系統,往往會觸發下游系統的Bug導致雪崩;
  • 多引擎執行:對於HQL的任務,可以透明切換到Hive和Spark執行,目前小時頻率的核心任務已經都穩定跑在Spark引擎上;
圖11  錯誤日誌的常見處理策略
圖11 錯誤日誌的常見處理策略
  • 鏈路分析

    1. DAG出度分析,評估任務重要程度,同時也是提供給排程系統的重要特徵;
    2. 執行趨勢分析,包括啟動時間,執行時長,處理資料量的趨勢變化;
    3. 通過埋點將使用者級別的任務和下游系統(Hadoop等)的任務全鏈路打通,可以追溯到任何一個層面執行狀況;同時,會給任務打標籤,比如傾斜、引數不合理等提供給使用者進行快速的自助分析和管理;
    4. 對錯誤日誌進行歸類處理,去掉噪音,並附上常見的處理策略,進一步提升任務自助化管理。
  • 告警:可以設定靈活的告警策略和觸達渠道,主要是輔助任務負責人或者值班人員。

報表開發平臺

報表開發是資料應用非常常見的一個場景,在大資料部門成立初期有大量的報表開發工作需要消耗很多人力,雖然有很多成熟的商業產品,但是大多專注於互動視覺化,對於已有系統和基礎設施的接入成本很高,因此我們快速開發了報表開發平臺(EMA)。

可以將模板化的SQL快速轉成報表嵌入到各個系統中,並且和內部系統打通,血緣建立,支援包括MySQL/Preso/Kylin/Hive/Spark等各種常見的資料來源或執行引擎,同時可配置報表查詢快取使得大計算量小結果集的場景得到很好滿足。EMA上線至今,有接近八成的報表都是出自該系統。

圖12  報表開發平臺應用
圖12 報表開發平臺應用

實時開發平臺

線上演算法的實時特徵計算包括POI感知、上下文場景感知,都是很典型的實時計算場景。實時開發管理平臺主要包括資料來源的端到端接入,封裝框架的業務無關細節,提供可配置策略,另外利用flux將任務配置和拓撲管理抽象出來。任務的釋出控制以及上線後自動監控聯動,讓開發人員更多關注業務邏輯和架構設計,減少管理層面的投入。

圖13  實時開發平臺的架構設計
圖13 實時開發平臺的架構設計

平臺的一些思考

  • 溝通和協調是最大的成本,Do not take things personally

    1. 面向使用者:儘量推動助化,和產品的自解釋;
    2. 反覆強化使用者預期;
    3. 面向系統:推動系統的自動化和一鍵化,最後才是SOP。
  • What gets measured gets fixed

    • 設計方面

      1. Less is more
      2. Think about future, design with flexibility,but only implement for production
    • 技術或方案選型

      1. 最合適的,而不是最先進的
      2. 清楚假設的邊界
      3. 技術要面向業務效率,產品不足服務湊

以上是我們截止到17年H1的一個回顧,餓了麼大資料平臺還在持續快速演進中,期待有更多的乾貨在接下來能夠和各位技術同仁共同交流探討。

作者:畢洪宇,餓了麼大資料平臺總監。曾在eBay,PPTV任職DBA。2012年加入唯品會,依次經歷從0到1參與資料庫基礎建設, 大資料基礎平臺和實時計算平臺的工作;2016年加入餓了麼負責大資料基礎架構,資料平臺工具鏈以及資料倉庫的工作。
責編:郭芮