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

當初面臨的問題
餓了么已經成立9年時間,相對而言數據平台團隊非常年輕,在加入團隊之初面臨了如下挑戰:
- 人少活多 積累不足
- 內在質量 “差不多就行”
- 故障處理 “千人千面”
因此,主要以效率、質量和持續擴展為核心來建設數據平台。
技術選型
如圖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計算場景是比較典型的流計算問題。

異步
分渠道訂單指標計算需要將主站訂單流和開發平台訂單流進行Join計算,因為是多數據流的合並計算,所以在設計該架構時基於的假設是:不同源數據流之間的到達時間無法協同,我們將問題轉化為”在可調整的時間窗口內通過匹配觸發Join計算”。具體落地則是通過Redis緩存住還沒有匹配的訂單數據,引入時間窗口是為了控制住緩存的大小,而時間窗口的控制有兩處:在拿到數據時會檢查是否在時間窗口內;另外在未匹配的情況下寫入Redis時會把時間窗口通過TTL的方式一並維護,避免多余的維護任務。
可擴展性
UV計算首先要解決的就是去重問題,比如判斷某個deviceID是否是當天的平台新訪客,一種做法是通過Redis的集合來判斷,具體數據結構如下:
key : YYYYMMDD_uv
value : deviceID的集合
- 1
- 2
這樣的設計會帶來熱點問題,所有該維度的deviceID請求都會打到一個節點上產生熱點,當流量增加時無法通過直接擴容來解決問題,那么自然就想到如下的數據結構:
key : _YYYYMMDD
value : 占位符
- 1
- 2
通過如此轉化可以很好地把請求打散,有具更好的擴展性。
回到多維度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),強調可持續的穩定性。

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

盡量擴大工具在整個數據工作生命周期的覆蓋度,為數據工作人員賦能,主要包括:
- 元數據管理:指標管理,數據質量監控,血緣關系追溯等;
- 權限管理及數據安全:數據底層的安全,基礎設施權限體系打通,以及數據使用安全;
- 數據開發管理:數據表管理,數據探查,離線與實時數據開發和任務運營;
- 數據應用:數據接口開發(SQL即接口),數據報表開發(SQL即報表)和管理;
- 自動化運營:整個基礎設施的管理,包括CMDB、工作流引擎、容量規划、性能分析與告警管控等。
本文着重分享數據開發管理和數據報表開發。

數據表管理
生產數據表是所有數據開發工作的源頭,因此我們把生產數據表的創建及維護工作統一收到數據表管理系統(以下稱dtmeta)中,除了建表的基礎功能外,主要關注如下信息:
- 靜態數據:表所屬主題,字段是維度還是度量,是否敏感或加密字段,表的生命周期和備份周期以及表的物理結構信息等;
- 動態數據:主要包含表的讀寫熱度情況,以及表的容量變化情況,便於針對性策略優化和問題分析。
有了這些信息,減少了大量后續維護的工作,降低交互成本。
數據開發及任務管理系統
數據開發
- 模板化:數據開發工作者可以直接在系統中開發ETL任務,支持動態變量,同時可配置觸發方式、期望完成時間等屬性,作為特征提供給調度系統;
- hook:在任務啟動前和執行結束后可以觸發的action,比如數據源的延遲檢測,數據抽取后的數據校驗或者推送后臨時數據狀態的清理(觸發)等;
- 依賴識別:對於基於依賴觸發的任務來說,依賴的自動化識別非常必要,人工配置依賴會遇到循環依賴以及依賴遺漏,從而影響任務的SLA甚至數據質量;
- 多數據存儲推送 :Hive通過外部表的方式支持向ES、Redis、Cassandra、MongoDB等數據存儲的推送以及抽取,簡化數據開發過程中的數據交換工作。


任務執行與管理
對於任務執行和任務的自助化運營管理我們主要關注這幾點:
- 壓力感知:會感任務運行的目標系統比如Yarn的壓力,達到反壓的效果而不是持續將任務直接提交給目標系統,往往會觸發下游系統的Bug導致雪崩;
- 多引擎執行:對於HQL的任務,可以透明切換到Hive和Spark執行,目前小時頻率的核心任務已經都穩定跑在Spark引擎上;

-
鏈路分析
- DAG出度分析,評估任務重要程度,同時也是提供給調度系統的重要特征;
- 運行趨勢分析,包括啟動時間,運行時長,處理數據量的趨勢變化;
- 通過埋點將用戶級別的任務和下游系統(Hadoop等)的任務全鏈路打通,可以追溯到任何一個層面執行狀況;同時,會給任務打標簽,比如傾斜、參數不合理等提供給用戶進行快速的自助分析和管理;
- 對錯誤日志進行歸類處理,去掉噪音,並附上常見的處理策略,進一步提升任務自助化管理。
-
告警:可以設置靈活的告警策略和觸達渠道,主要是輔助任務負責人或者值班人員。
報表開發平台
報表開發是數據應用非常常見的一個場景,在大數據部門成立初期有大量的報表開發工作需要消耗很多人力,雖然有很多成熟的商業產品,但是大多專注於交互可視化,對於已有系統和基礎設施的接入成本很高,因此我們快速開發了報表開發平台(EMA)。
可以將模板化的SQL快速轉成報表嵌入到各個系統中,並且和內部系統打通,血緣建立,支持包括MySQL/Preso/Kylin/Hive/Spark等各種常見的數據源或執行引擎,同時可配置報表查詢緩存使得大計算量小結果集的場景得到很好滿足。EMA上線至今,有接近八成的報表都是出自該系統。

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

平台的一些思考
-
溝通和協調是最大的成本,Do not take things personally
- 面向用戶:盡量推動助化,和產品的自解釋;
- 反復強化用戶預期;
- 面向系統:推動系統的自動化和一鍵化,最后才是SOP。
-
What gets measured gets fixed
-
設計方面
- Less is more
- Think about future, design with flexibility,but only implement for production
-
技術或方案選型
- 最合適的,而不是最先進的
- 清楚假設的邊界
- 技術要面向業務效率,產品不足服務湊
-
以上是我們截止到17年H1的一個回顧,餓了么大數據平台還在持續快速演進中,期待有更多的干貨在接下來能夠和各位技術同仁共同交流探討。