餓了麼大資料計算引擎實踐與應用
餓了麼BDI-大資料平臺研發團隊目前共有20人左右,主要負責離線&實時Infra和平臺工具開發。其中6人的離線團隊需要維護大資料叢集規模如下:
- Hadoop叢集規模1300+
- HDFS存量資料40+PB,Read 3.5 PB+/天,Write 500TB+/天
- 14W MR Job/天,10W Spark Job/天,25W Presto/天
此外還需要維護Hadoop、Spark、Hive、Presto等元件餓了麼內部版本,解決公司400+大資料叢集使用者每天面臨的各種問題。
本文主要介紹餓了麼大資料團隊如何通過對計算引擎入口的統一,降低使用者接入門檻。如何讓使用者自助分析任務異常及失敗原因,以及如何從叢集產生的任務資料本身監控叢集計算/儲存資源消耗,監控叢集狀況,監控異常任務等。
引擎入口統一
目前在餓了麼對外提供的查詢引擎主要有Presto、Hive和Spark,其中Spark又有SparkThrift Server和Spark SQL兩種模式,並且Kylin也在穩步試用中,Druid也正在調研中。各種計算引擎都有自身的優缺點,適用的計算場景各不相同。
從使用者角度來說,普通使用者對此沒有較強的辨識能力,學習成本會比較高。並且當用戶可以自主選擇引擎執行任務時,會優先選擇所謂的最快引擎,而這勢必會造成引擎阻塞,或者將完全不適合的任務提交到某引擎,從而降低任務成功率。
從管理角度來說,大資料叢集的入口太多,將難以實現統一管理,難以實現負載均衡、許可權控制,難以掌控叢集整體對外服務能力。並且當有新的計算需求需要接入,我們還需要為其部署對應的客戶端環境。
功能模組
針對這種情況,餓了麼大資料團隊開發了Dispatcher,該元件的主要功能如下圖所示:
使用者所有任務全部通過Dispatcher提交,在Dispatcher中我們可以做到統一的鑑權,統一的任務執行情況跟蹤。還可以做到執行引擎的自動路由,各執行引擎負載控制,以及通過引擎降級提高任務執行成功率。
邏輯架構
Dispatcher的邏輯架構如下圖所示:
目前使用者可以通過JDBC模式呼叫Dispatcher服務,或者直接以Driver模式執行Dispatcher。Dispatcher接收到查詢請求後,將會統一進行鑑權、引擎路由等操作將查詢提交到對應引擎。另外,Dispatcher還有SQL轉換模組,當發生從Presto引擎降級到Spark/Hive引擎時,將會通過該模組自動將Presto SQL轉換成HiveQL。
通過Dispatcher對查詢入口的統一,帶來的好處如下:
- 使用者接入門檻低,無需再去學習各引擎使用方法和優缺點,無需手動選擇執行引擎;
- 部署成本低,客戶端可通過JDBC方式快速接入;
- 統一的鑑權和監控;
- 降級模組提高任務成功率;
- 各引擎負載均衡;
- 引擎可擴充套件。
引擎可擴充套件主要是指當後續接入Kylin、Druid或者其他更多查詢引擎時,可以做到使用者無感知。由於收集到了提交到叢集的所有查詢,針對每一個已有查詢計劃,我們可以獲得熱度資料,知道在全部查詢中哪些表被使用次數最多,哪些表經常被關聯查詢,哪些欄位經常被聚合查詢等,當後續接入Kylin時,可以通過這些資料快速建立或優化Cube。
SQL畫像
在Dispatcher中最核心的是SQL畫像模組,基本流程如下圖:
查詢提交後,通過連線HiveServer對查詢計劃進行解析,可以獲取當前查詢的所有元資料資訊,比如:
- 讀入資料量
- 讀入表/分割槽數
- 各類Join次數
- 關聯欄位多少
- 聚合複雜度
- 過濾條件
- ……
上述元資料資訊基本上可以對每一個查詢進行精準的描述,每一個查詢可以通過這些維度的統計資訊排程到不同引擎中。
Hive對SQL進行解析並進行邏輯執行計劃優化後,將會得到優化後的Operator Tree,通過explain命令可以檢視。SQL畫像資料可以從這個結果收集各種不同型別的Operator操作,如下圖所示:
從直觀的理解上我們知道,讀入資料量對於引擎的選擇是很重要的。比如當讀入少量資料時,Presto執行效能最好,讀入大量資料時Hive最穩定,而當讀入中等資料量時,可以由Spark來執行。
在初始階段,還可以通過讀入資料量,結合Join複雜度,聚合複雜度等因素在各種計算引擎上進行測試,採用基於規則的辦法進行路由。執行過程中記錄好每一次查詢的SQL畫像資料,執行引擎,降級鏈路等資料。基於這些畫像資料,後續可以採用比如決策樹,Logistic迴歸,SVM等分類演算法實現引擎的智慧路由,目前餓了麼大資料團隊已經開始了這方面的嘗試。
目前在餓了麼的應用中,由Dispatcher統一排程的Ad Hoc查詢,由於增加了預檢查環節,以及失敗降級環節,每天總體成功率為99.95%以上,整體PT90值為300秒左右。目前Presto承擔了Ad Hoc查詢的50%流量,SparkServer模式承擔了40%流量。
充分利用叢集本身資料
餓了麼大資料叢集每天執行的Spark&MR任務25W+,這些資料詳細記錄了每一個Mapper/Reducer或者Spark的Task的執行情況,如果能夠充分利用,將會產生巨大的價值。充分利用叢集本身資料,資料驅動叢集建設。這些資料不僅可以有助於叢集管理人員監控叢集本身的計算資源、儲存資源消耗,任務效能分析,主機執行狀態。還可以幫助使用者自助分析任務執行失敗原因,任務執行效能分析等。
餓了麼大資料團隊開發的Grace專案就是在這方面的一個示例。
Grace使用場景
對叢集任務執行狀況詳細資料沒有明確認識的話,很容易當出現問題時陷入困境,從監控看到叢集異常後將無法繼續進一步快速定位問題。
當經常有使用者找你說,我的任務為什麼跑失敗了?我的任務為什麼跑的這麼慢?我的任務能調一下優先順序麼?不要跟我說看日誌,我看不懂。我想大家內心都是崩潰的。
當監控發出NameNode異常抖動,網路飈高,block建立增加,block建立延時增大等告警時,應該如何快速定位叢集執行的異常任務?
當監控發出叢集中Pending的任務太多時,使用者反饋任務大面積延遲時,如何快速找到問題根本原因?
當用戶申請計算資源時,到底應該給他們分配多少資源?當用戶申請提高任務優先順序時如何用資料說話,明確優先順序到底應該調到多少?當用戶只管上線不管下線任務時,我們如何定位哪些任務是不再需要的?
還有,如何通過實時展示各BU計算資源消耗,指定BU中各使用者計算資源消耗,佔BU資源比例。以及如何從歷史資料中分析各BU任務數,資源使用比例,BU內部各使用者的資源消耗,各任務的資源消耗等。
以下示例展示一些Grace產出資料圖表。有關BU、使用者、任務級別的資料不方便展示。
1)監控佇列
從下圖可以方便的看到各佇列最大最小資源,當前已用資源,當前執行任務數,Pending任務數,以及資源使用比例等,還可以看到這些資料的歷史趨勢。
2)任務監控
可以檢視指定佇列中執行中任務的任務型別,開始時間,執行時長,消耗當前佇列資源比例,以及消耗當前BU資源比例等。可快速定位計算資源消耗多並且執行時間長的任務,快速找到佇列阻塞原因。
3)監控主機失敗率
可以監控叢集所有主機上的Task執行失敗率。已有監控體系會對主機的CPU,磁碟,記憶體,網路等硬體狀況進行監控。這些硬體故障最直觀的表現就是分配在這些有問題的主機上的任務執行緩慢或者執行失敗。執行中的任務是最靈敏的反應,一旦檢測到某主機失敗率過高,可觸發快速自動下線保障業務正常執行。後續可以結合硬體監控定位主機異常原因。
4)任務效能分析
使用者可自助進行任務效能分析。
並且可以根據異常項根據以下建議自助調整。
5)任務失敗原因分析
對於失敗的任務,使用者也可以按照以下方法快速從排程系統檢視失敗原因,以及對應的解決辦法,餓了麼大資料團隊會定期收集各種典型報錯資訊,更新維護自助分析知識庫。
失敗原因自助分析
除此之外,我們還可以實時監控每個任務的計算資源消耗GB Hours,總的讀入寫出資料量,Shuffle資料量等。以及執行中任務的HDFS讀寫資料量,HDFS運算元等。
當出現叢集計算資源不足時,可快速定位消耗計算資源多的任務。當監控出現HDFS叢集抖動,讀寫超時等異常狀況時,也可通過這些資料快速定位到異常任務。
基於這些資料還可以根據各佇列任務量,任務執行資源消耗時間段分佈,合理優化各佇列資源分配比例。
根據這些任務執行狀況資料建立任務畫像,監控任務資源消耗趨勢,定位任務是否異常。再結合任務產出資料的訪問熱度,還可以反饋給排程系統動態調整任務優先順序等。
Grace架構
上述示例中使用到的資料都是通過Grace收集的。Grace是餓了麼大資料團隊開發的應用,主要用於監控分析線上MR/Spark任務執行資料,監控執行中佇列及任務明細及彙總資料。邏輯架構如下:
Grace是通過Spark Streaming實現的,通過消費Kafka中儲存的已完成MR任務的jhist檔案或Spark任務的eventlog路徑,從HDFS對應位置獲取任務執行歷史資料,解析後得到MR/Spark任務的明細資料。再根據這些資料進行一定的聚合分析,得到任務級別,Job級別,Stage級別的彙總資訊。最後通過定製化的Dr-Elephant系統對任務明細資料通過啟發式演算法進行分析,從而給使用者一些直觀化的優化提示。
對於Dr-Elephant,我們也做了定製化的變動,比如將其作為Grace體系的一個元件打包依賴。從單機部署服務的模式變成了分散式實時解析模式。將其資料來源切換為Grace解析到的任務明細資料。增加每個任務的ActionId跟蹤鏈路資訊,優化Spark任務解析邏輯,增加新的啟發式演算法和新的監控指標等。
總結
隨著大資料生態體系越來越完善,越來越多背景不同的使用者都將加入該生態圈,我們如何降低使用者的進入門檻,方便使用者快速便捷地使用大資料資源,也是需要考慮的問題。
大資料叢集中執行的絕大部分任務都是業務相關,但是隨著叢集規模越來越大,任務規模越來越大,叢集本身產生的資料也是不容忽視的。這部分資料才是真正反映叢集使用詳細情況的,我們需要考慮如何收集使用這部分資料,從資料角度來衡量、觀察我們的叢集和任務。
僅僅關注於叢集整體部署、效能、穩定等方面是不夠的,如何提高使用者體驗,充分挖掘叢集本身資料,用資料促進大資料叢集的建設,是本次分享的主題。
Q & A
Q:能簡單介紹一下排程系統嗎?管理上萬個任務不容易。
A:
- 排程系統說起來挺複雜的。就提幾個關鍵點吧,一個是任務之間的依賴,一個是血緣關係,一個是任務與例項,還有叢集反壓、分散式排程、底層環境統一。
- 其中血緣關係應該是必須的,因為當你叢集規模大了之後,使用者配置任務時根本無法完整地新增依賴。
- 通過血緣系統,對任務進行解析,當用戶配置好新任務後,自動推薦前置依賴,保證任務有序執行。
Q:如何得出叢集的每天讀寫規模?Hadoop有介面?
A:
- 叢集讀寫規模是通過前面介紹的Grace收集的。因為我們會分析每個mr task或者spark task的HDFS資料讀寫量。還包括spill到磁碟的資料量、shuffle write、shuffle read資料量,以及每個任務的GBHour資訊。
- 其實這些資料你通過YARN或者Spark的WEB UI頁面都能看到,你需要做的只是實時地去解析,收集這些資料。這也是本次分享介紹中提到的,從資料角度運維叢集。
- 除了業務資料之外,叢集本身產生的資料也很有價值。
Q:這個就是從大資料本身產出的資料來精細化運維叢集吧?
A:
- 是的。
- 如果你也從事資料架構方向的話,可以回想一下自己每天的工作內容。我們只不過是把人肉分析變成自動化,然後再加入一些實時性。