餓了麼元數據管理實踐之路

一、背景

大數據挑戰

大數據時代,餓了麼面臨數據管理、數據使用、數據問題等多重挑戰。具體可以參考下圖:

image.png

數據問題:多種執行、存儲引擎,分鐘、小時、天級的任務調度,怎樣梳理數據的時間線變化?
數據使用:任務、表、列、指標等數據,如何進行檢索、複用、清理、熱度Top計算?
數據管理:怎樣對錶、列、指標等進行權限控制、任務治理以及上下游依賴影響分析?

元數據定義與價值

元數據打通數據源、數據倉庫、數據應用,記錄了數據從產生到消費的完整鏈路。它包含靜態的表、列、分區信息(也就是MetaStore);動態的任務、表依賴映射關係;數據倉庫的模型定義、數據生命週期;以及ETL任務調度信息、輸入輸出等。

元數據是數據管理、數據內容、數據應用的基礎。例如可以利用元數據構建任務、表、列、用戶之間的數據圖譜;構建任務DAG依賴關係,編排任務執行序列;構建任務畫像,進行任務質量治理;數據分析時,使用數據圖譜進行字典檢索;根據表名查看錶詳情,以及每張表的來源、去向,每個字段的加工邏輯;提供個人或BU的資產管理、計算資源消耗概覽等。

開源解決方案

image.png

WhereHows是LinkedIn開源的元數據治理方案。Azkaban調度器抓取job執行日誌,也就是Hadoop的JobHistory,Log Parser後保存DB,並提供REST查詢。WhereHows太重,需要部署Azkaban等調度器,以及只支持表血緣,功能侷限。

image.png

Atlas是Apache開源的元數據治理方案。Hook執行中採集數據(比如HiveHook),發送Kafka,消費Kafka數據,生成Relation關係保存圖數據庫Titan,並提供REST接口查詢功能,支持表血緣,列級支持不完善。

二、餓了麼元數據系統架構

image.png

DB保存任務的SQL數據、任務基礎信息、執行引擎上下文信息;
Extract循環抽取SQL並解析成表、列級血緣Lineage;
DataSet包含Lineage關係數據+任務信息+引擎上下文;
將DataSet數據集保存到Neo4j,並提供關係查詢;保存ES,提供表、字段等信息檢索。

SQL埋點與採集

image.png


餓了麼的SQL數據,以執行中採集爲主+保存前submit爲輔。因爲任務的SQL可能包含一些時間變量,比如dt、hour,以及任務可能是天調度、小時調度。執行中採集SQL實時性更高,也更容易處理。

EDW是餓了麼的調度系統,類比開源的AirFlow。調度系統執行任務,並將任務相關的信息,比如appId、jobId、owner、SQL等信息存入DB。

計算引擎實現相關的監聽接口,比如Hive實現Execute With Hook Context接口;Spark實現Spark Listener接口;Presto實現Event Listener接口。將計算引擎相關的上下文Context、元數據MetaData、統計Statistics等信息存入DB。

SQL解析

解析SQL的方案,以Hive爲例。先定義詞法規則和語法規則文件,然後使用Antlr實現SQL的詞法和語法解析,生成AST語法樹,遍歷AST語法樹完成後續操作。

但對於SELECT *、CTAS等操作,直接遍歷AST,不去獲取Schema信息來檢查表名、列名,就無法判定SQL的正確性,導致數據污染。

綜上所述,餓了麼的SQL解析方案,直接參考Hive的底層源碼實現。

image.png

以本土做簡單示例,先經過Semantic Analyzer Factory類進行語法分析,再根據Schema生成執行計劃QueryPlan。關於表、列的血緣,可以從LineageInfo、LineageLogger類中獲得解決方案。

當然,你需要針對部分類型SQL設置Hive Conf,比如“開啓動態分區非嚴格模式”。對於CTAS類型,需要設置Context。UDF函數需要修改部分Hive源碼,避免UDF Registry檢查。

image.png

餓了麼解析血緣的SQL支持的操作有:Query(包含selectinsert intoinsert overwrite)、CreateTable、CreateTableAsSelect、DropTable、CreateView、AlterView。基本覆蓋餓了麼生產環境99%+的SQL語法。

舉個栗子

image.png

舉個栗子,根據上面的SQL,分別產生表、列血緣結構。

input是表、列輸入值;output是表、列輸出值;operation代表操作類型。比如表A+B通過insert,生成表C,則延展成A insert C; B insert C。

列式也一樣:

input:name, 
operation: coalesce(name, count(id)), 
output: lineage_name;

input: id, 
operation: coalesce(name, count(id)), 
output
:lineage_name

表血緣結構

image.png

列血緣結構

image.png

圖存儲

image.png

image.png

有了input、operation、output關係,將input、output保存爲圖節點,operation保存爲圖邊。圖數據庫選用Gremlin+Neo4j。

Gremlin是圖語言,存儲實現方案比較多,Cypher查詢不太直觀,且只能Neo4j使用。社區版Neo4j只能單機跑,我們正在測試OrientDB。

三、餓了麼部分使用場景

下面是餓了麼在元數據應用上的部分場景:

image.png

靜態的Hive MetaStore表,比如DBS、TBLS、SDS、COLUMNS_V2、TABLE_PARAMS、PARTITIONS,保存表、字段、分區、Owner等基礎信息,便於表、字段的信息檢索功能。

image.png

提供動態的表依賴血緣關係查詢。節點是表基礎信息,節點之間的邊是Operation信息,同時附加任務執行Id、執行時間等屬性。列血緣結構展示等同表血緣結構。

image.png

根據SQL的input、output構建表的依賴關係,進一步構建任務的DAG依賴結構。可以對任務進行DAG調度,重新編排任務執行序列。

Q & A

Q1:咱們的數據生命週期是如何管理的,能具體說下嗎?
A:表級數據進行熱度分析,比如近三個月沒人訪問,是否可以下線,特別是一些臨時表 需要定時清理。

Q2:質量監控會影響到任務調度編排麼?
A:會影響質量編排,構建DAG依賴執行。

Q3:把從SQL中的埋點數據存儲到MySQL中,是如何規劃的?這些埋點信息不應該像是日誌數據一樣被處理嗎?存儲在MySQL中是有自增全局ID的麼?還是說你們是對任務和表分別有MySQL表,然後更新MySQL表中任務和表甚至列的信息麼?這裏的MySQL表就是您說的DataSet麼?
A:任務jobid進行唯一,MySQL只保存執行的SQL,以及任務本身的信息,比如owner time jobid等等。

Q4:當前的支持非SQL形式生成表麼?比如直接用Spark RDD任務或者Spark MLlib任務取表和生成表?
A:只支持SQL表達。

Q5:你們是怎麼做熱度分析的?剛纔的講解裏,這個點講得比較少。
A:任務操作的SQL產生input output表,對錶進行counter就能top counter,列也一樣。

Q6:你們管理的表分線上表和線下表麼?在處理的時候用到了一些臨時表該怎麼處理?
A:對的,線上還是線下,任務調度系統埋點,臨時表根據temp就知道了。

Q7:數據血緣關係如果使用Hive hook方式獲取,是需要在每個執行節點中做捕捉嗎?
A:Hive hook就是執行時調用,可以去了解下底層。

Q8:解析那種複雜度很高的HQL的血緣,你們平臺的解析思路是什麼樣子的?如何保證正確率呢?
A:會有很多複雜的ppt有代碼示例,會有部分SQL需要修改Hive解析實現。

Q9:表血緣圖裏面的上下級關係就是數據的流向?從上到下?字段的血緣是什麼樣子的跟表的血緣有什麼不同?有字段的血緣圖嗎?
A:ppt裏解析那裏可以看到,字段也一樣,input output列然後operation

Q10:SQL埋點,引擎埋點,是要去重寫Hive等的源碼嗎?
A:重寫倒不至於,只要實現ppt裏的接口,很簡單。

 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章