作者:朱良
本文主要介紹一種通用的實時數倉建構的方法與實踐。實時數倉以端到端低延遲、SQL 标準化、快速響應變化、資料統一為目标。
在實踐中,我們總結的最佳實踐是:一個通用的實時生産平台 + 一個通用互動式實時分析引擎互相配合同時滿足實時和準實時業務場景。兩者合理分工,互相補充,形成易于開發、易于維護、效率最高的流水線,兼顧開發效率與生産成本,以較好的投入産出比滿足業務多樣需求。
01 實時場景
實時資料在美團外賣的場景是非常多的,主要有以下幾點:
- 營運層面:比如實時業務變化,實時營銷效果,當日營業情況以及當日實時業務趨勢分析等。
- 生産層面:比如實時系統是否可靠,系統是否穩定,實時監控系統的健康狀況等。
- C 端使用者:比如搜尋推薦排序,需要實時了解使用者的想法,行為、特點,給使用者推薦更加關注的内容。
- 風控側:在外賣以及金融科技用的是非常多的,實時風險識别,反欺詐,異常交易等,都是大量應用實時資料的場景
02 實時技術及架構
1. 實時計算技術選型
目前開源的實時技術比較多,比較通用的是 Storm、Spark Streaming 以及 Flink,具體要根據不同公司的業務情況進行選型。
美團外賣是依托美團整體的基礎資料體系建設,從技術成熟度來講,前幾年用的是 Storm,Storm 當時在性能穩定性、可靠性以及擴充性上是無可替代的,随着 Flink 越來越成熟,從技術性能上以及架構設計優勢上已經超越Storm,從趨勢來講就像 Spark 替代 MR 一樣,Storm 也會慢慢被 Flink 替代,當然從 Storm 遷移到 Flink 會有一個過程,我們目前有一些老的任務仍然在 Storm 上,也在不斷推進任務遷移。
具體 Storm 和 Flink 的對比可以參考上圖表格。
2. 實時架構
① Lambda 架構
Lambda 架構是比較經典的架構,以前實時的場景不是很多,以離線為主,當附加了實時場景後,由于離線和實時的時效性不同,導緻技術生态是不一樣的。Lambda 架構相當于附加了一條實時生産鍊路,在應用層面進行一個整合,雙路生産,各自獨立。這在業務應用中也是順理成章采用的一種方式。
雙路生産會存在一些問題,比如加工邏輯 double,開發運維也會 double,資源同樣會變成兩個資源鍊路。因為存在以上問題,是以又演進了一個 Kappa 架構。
② Kappa 架構
Kappa 架構從架構設計來講比較簡單,生産統一,一套邏輯同時生産離線和實時。但是在實際應用場景有比較大的局限性,在業内直接用 Kappa 架構生産落地的案例不多見,且場景比較單一。這些問題在我們這邊同樣會遇到,我們也會有自己的一些思考,在後面會講到。
03 業務痛點
在外賣業務上,我們也遇到了一些問題。
業務早期,為了滿足業務需要,一般是拿到需求後 case by case 的先把需求完成,業務對于實時性要求是很高的,從時效性來說,沒有進行中間層沉澱的機會,在這種場景下,一般是拿到業務邏輯直接嵌入,這是能想到的簡單有效的方法,在業務發展初期這種開發模式比較常見。
如上圖所示,拿到資料源後,會經過資料清洗,擴維,通過 Storm 或 Flink 進行業務邏輯處理,最後直接進行業務輸出。把這個環節拆開來看,資料源端會重複引用相同的資料源,後面進行清洗、過濾、擴維等操作,都要重複做一遍,唯一不同的是業務的代碼邏輯是不一樣的,如果業務較少,這種模式還可以接受,但當後續業務量上去後,會出現誰開發誰運維的情況,維護工作量會越來越大,作業無法形成統一管理。而且所有人都在申請資源,導緻資源成本急速膨脹,資源不能集約有效利用,是以要思考如何從整體來進行實時資料的建設。
04 資料特點與應用場景
那麼如何來建構實時數倉呢?
首先要進行拆解,有哪些資料,有哪些場景,這些場景有哪些共同特點,對于外賣場景來說一共有兩大類,日志類和業務類。
- 日志類:資料量特别大,半結構化,嵌套比較深。日志類的資料有個很大的特點,日志流一旦形成是不會變的,通過埋點的方式收集平台所有的日志,統一進行采集分發,就像一顆樹,樹根非常大,推到前端應用的時候,相當于從樹根到樹枝分叉的過程(從 1 到 n 的分解過程),如果所有的業務都從根上找資料,看起來路徑最短,但包袱太重,資料檢索效率低。日志類資料一般用于生産監控和使用者行為分析,時效性要求比較高,時間視窗一般是 5min 或 10min 或截止到目前的一個狀态,主要的應用是實時大屏和實時特征,例如使用者每一次點選行為都能夠立刻感覺到等需求。
- 業務類:主要是業務交易資料,業務系統一般是自成體系的,以 Binlog 日志的形式往下分發,業務系統都是事務型的,主要采用範式模組化方式,特點是結構化的,主體非常清晰,但資料表較多,需要多表關聯才能表達完整業務,是以是一個 n 到 1 的內建加工過程。
業務類實時處理面臨的幾個難點:
- 業務的多狀态性:業務過程從開始到結束是不斷變化的,比如從下單->支付->配送,業務庫是在原始基礎上進行變更的,binlog 會産生很多變化的日志。而業務分析更加關注最終狀态,由此産生資料回撤計算的問題,例如 10 點下單,13 點取消,但希望在 10 點減掉取消單。
- 業務內建:業務分析資料一般無法通過單一主體表達,往往是很多表進行關聯,才能得到想要的資訊,在實時流中進行資料的合流對齊,往往需要較大的緩存處理且複雜。
- 分析是批量的,處理過程是流式的:對單一資料,無法形成分析,是以分析對象一定是批量的,而資料加工是逐條的。
日志類和業務類的場景一般是同時存在的,交織在一起,無論是 Lambda 架構還是 Kappa 架構,單一的應用都會有一些問題。是以針對場景來選擇架構與實踐才更有意義。
05 實時數倉架構設計
1. 實時架構:流批結合的探索
基于以上問題,我們有自己的思考。通過流批結合的方式來應對不同的業務場景。
如上圖所示,資料從日志統一采集到消息隊列,再到資料流的 ETL 過程,作為基礎資料流的建設是統一的。之後對于日志類實時特征,實時大屏類應用走實時流計算。對于 Binlog 類業務分析走實時 OLAP 批處理。
流式處理分析業務的痛點?對于範式業務,Storm 和 Flink 都需要很大的外存,來實作資料流之間的業務對齊,需要大量的計算資源。且由于外存的限制,必須進行視窗的限定政策,最終可能放棄一些資料。計算之後,一般是存到 Redis 裡做查詢支撐,且 KV 存儲在應對分析類查詢場景中也有較多局限。
實時 OLAP 怎麼實作?有沒有一種自帶存儲的實時計算引擎,當實時資料來了之後,可以靈活的在一定範圍内自由計算,并且有一定的資料承載能力,同時支援分析查詢響應呢?随着技術的發展,目前 MPP 引擎發展非常迅速,性能也在飛快提升,是以在這種場景下就有了一種新的可能。這裡我們使用的是 Doris 引擎。
這種想法在業内也已經有實踐,且成為一個重要探索方向。阿裡基于 ADB 的實時 OLAP 方案等。
2. 實時數倉架構設計
從整個實時數倉架構來看,首先考慮的是如何管理所有的實時資料,資源如何有效整合,資料如何進行建設。
從方法論來講,實時和離線是非常相似的,離線數倉早期的時候也是 case by case,當資料規模漲到一定量的時候才會考慮如何治理。分層是一種非常有效的資料治理方式,是以在實時數倉如何進行管理的問題上,首先考慮的也是分層的處理邏輯,具體如下:
- 資料源:在資料源的層面,離線和實時在資料源是一緻的,主要分為日志類和業務類,日志類又包括使用者日志,DB 日志以及伺服器日志等。
- 實時明細層:在明細層,為了解決重複建設的問題,要進行統一建構,利用離線數倉的模式,建設統一的基礎明細資料層,按照主題進行管理,明細層的目的是給下遊提供直接可用的資料,是以要對基礎層進行統一的加工,比如清洗、過濾、擴維等。
- 彙總層:彙總層通過 Flink 或 Storm 的簡潔算子直接可以算出結果,并且形成彙總名額池,所有的名額都統一在彙總層加工,所有人按照統一的規範管理建設,形成可複用的彙總結果。
總結起來,從整個實時數倉的建設角度來講,首先資料建設的階層化要先建出來,先搭架構,然後定規範,每一層加工到什麼程度,每一層用什麼樣的方式,當規範定義出來後,便于在生産上進行标準化的加工。由于要保證時效性,設計的時候,層次不能太多,對于實時性要求比較高的場景,基本可以走上圖左側的資料流,對于批量處理的需求,可以從實時明細層導入到實時 OLAP 引擎裡,基于 OLAP 引擎自身的計算和查詢能力進行快速的回撤計算,如上圖右側的資料流。
06 實時平台化建設
架構确定之後,後面考慮的是如何進行平台化的建設,實時平台化建設完全附加于實時數倉管理之上進行的。
首先進行功能的抽象,把功能抽象成元件,這樣就可以達到标準化的生産,系統化的保障就可以更深入的建設,對于基礎加工層的清洗、過濾、合流、擴維、轉換、加密、篩選等功能都可以抽象出來,基礎層通過這種元件化的方式建構直接可用的資料結果流。這其中會有一個問題,使用者的需求多樣,滿足了這個使用者,如何相容其他的使用者,是以可能會出現備援加工的情況,從存儲來講,實時資料不存曆史,不會消耗過多的存儲,這種備援是可以接受的,通過備援的方式可以提高生産效率,是一種空間換時間的思想應用。
通過基礎層的加工,資料全部沉澱到 IDL 層,同時寫到 OLAP 引擎的基礎層,再往上是實時彙總層計算,基于 Storm、Flink 或 Doris,生産多元度的彙總名額,形成統一的彙總層,進行統一的存儲分發。
當這些功能都有了以後,中繼資料管理,名額管理,資料安全性、SLA、資料品質等系統能力也會逐漸建構起來。
1. 實時基礎層功能
實時基礎層的建設要解決一些問題。
首先是一條流重複讀的問題,一條 Binlog 打過來,是以 DB 包的形式存在的,使用者可能隻用其中一張表,如果大家都要用,可能存在所有人都要接這個流的問題。解決方案是可以按照不同的業務解構出來,還原到基礎資料流層,根據業務的需要做成範式結構,按照數倉的模組化方式進行內建化的主題建設。
其次要進行元件的封裝,比如基礎層的清洗、過濾、擴維等功能,通過一個很簡單的表達入口,讓使用者将邏輯寫出來。trans 環節是比較靈活的,比如從一個值轉換成另外一個值,對于這種自定義邏輯表達,我們也開放了自定義元件,可以通過 Java 或 Python 開發自定義腳本,進行資料加工。
2. 實時特征生産功能
特征生産可以通過 SQL 文法進行邏輯表達,底層進行邏輯的适配,透傳到計算引擎,屏蔽使用者對計算引擎的依賴。就像對于離線場景,目前大公司很少通過代碼的方式開發,除非一些特别的 case,是以基本上可以通過 SQL 化的方式表達。
在功能層面,把名額管理的思想融合進去,原子名額、派生名額,标準計算口徑,次元選擇,視窗設定等操作都可以通過配置化的方式,這樣可以統一解析生産邏輯,進行統一封裝。
還有一個問題,同一個源,寫了很多 SQL,每一次送出都會起一個資料流,比較浪費資源,我們的解決方案是,通過同一條流實作動态名額的生産,在不停服務的情況下可以動态添加名額。
是以在實時平台建設過程中,更多考慮的是如何更有效的利用資源,在哪些環節更能節約化的使用資源,這是在工程方面更多考慮的事情。
3. SLA 建設
SLA 主要解決兩個問題,一個是端到端的 SLA,一個是作業生産效率的 SLA,我們采用埋點+上報的方式,由于實時流比較大,埋點要盡量簡單,不能埋太多的東西,能表達業務即可,每個作業的輸出統一上報到 SLA 監控平台,通過統一接口的形式,在每一個作業點上報所需要的資訊,最後能夠統計到端到端的 SLA。
在實時生産中,由于鍊路非常長,無法控制所有鍊路,但是可以控制自己作業的效率,是以作業 SLA 也是必不可少的。
4. 實時 OLAP 方案
問題:
- Binlog 業務還原複雜:業務變化很多,需要某個時間點的變化,是以需要進行排序,并且資料要存起來,這對于記憶體和 CPU 的資源消耗都是非常大的。
- Binlog 業務關聯複雜:流式計算裡,流和流之間的關聯,對于業務邏輯的表達是非常困難的。
解決方案:
通過帶計算能力的 OLAP 引擎來解決,不需要把一個流進行邏輯化映射,隻需要解決資料實時穩定的入庫問題。
我們這邊采用的是 Doris 作為高性能的 OLAP 引擎,由于業務資料産生的結果和結果之間還需要進行衍生計算,Doris可以利用 unique 模型或聚合模型快速還原業務,還原業務的同時還可以進行彙總層的聚合,也是為了複用而設計。應用層可以是實體的,也可以是邏輯化視圖。
這種模式重在解決業務回撤計算,比如業務狀态改變,需要在曆史的某個點将值變更,這種場景用流計算的成本非常大,OLAP 模式可以很好的解決這個問題。
07 實時應用案例
最後通過一個案例說明,比如商家要根據使用者曆史下單數給使用者優惠,商家需要看到曆史下了多少單,曆史 T+1 的資料要有,今天實時的資料也要有,這種場景是典型的 Lambda 架構,可以在 Doris 裡設計一個分區表,一個是曆史分區,一個是今日分區,曆史分區可以通過離線的方式生産,今日名額可以通過實時的方式計算,寫到今日分區裡,查詢的時候進行一個簡單的彙總。
這種場景看起來比較簡單,難點在于商家的量上來之後,很多簡單的問題都會變的複雜,是以後面我們也會通過更多的業務輸入,沉澱出更多的業務場景,抽象出來形成統一的生産方案和功能,以最小化的實時計算資源支撐多樣化的業務需求,這也是未來需要達到的目的。
更多 Flink 技術交流可加入 Apache Flink 社群釘釘交流群: