摘要:本文整理自螞蟻實時數倉架構師馬年聖,在 Flink Forward Asia 2022 流批一體專場的分享。本篇內容主要分為四個部分:
- 實時應用場景與研發體系
- 低程式碼研發
- 流批一體
- 規劃展望
一、實時應用場景與研發體系
螞蟻實時的資料應用主要包括報表監控、實時標籤和實時特徵三部分。最底層的實時資料採集來源於線上日誌、實時訊息和資料庫日誌三大塊,並由此構建了實時和離線的明細中間層,該中間層定義不同的主題域,如:流量、營銷、交易等。再往上構建應用層資料去支撐前臺業務的實時資料需求。
在這三個應用場景中,報表場景根據查詢特性的不同,實時資料會被儲存到 OLAP 引擎或 KV 庫,在應用層進行實時/離線資料的融合,來構建實時資料包表;而在實時標籤場景,將實時資料直寫到 Hbase/Lindorm 庫中,離線資料透過標籤平臺迴流至線上庫中;特徵場景和標籤場景鏈路類似,透過特徵檢視對流/批資料分別進行欄位 Mapping。
以上的資料鏈路架構在研發、運維、消費的成本上均存在一定的問題,在開發階段,首先突出的是實時研發的效率問題,一個實時任務從需求對接到資料交付往往需要較長時間,如果涉及到離線回補邏輯,則還需開發離線兜底鏈路,並同步離線資料到線上庫中;在線上運維階段,雖然 Flink 一直在降低任務調優難度,但實時離線計算引擎的運維壓力是雙重的,往往需要互相翻譯口徑進行問題排查;在消費鏈路中,實時離線兩撥同學研發,往往報表會配置兩份,其工作量重複之餘,也會增加下游的資料使用成本。
最後再丟擲一個實時中的老大難問題:長週期計算問題。支付寶大促活動頻繁,計算活動期間累計去重 UV 這類指標,研發運維成本一直較高,這也是我們嘗試在最佳化解決的問題。
螞蟻實時研發體系在去年完成了的升級,構建了基於實時元表為載體的實時研發能力,從實時資產的定義、到實時程式碼研發、到線上的實時質量監控,再到實時後設資料消費,都是基於元表來完成的,在資料研發時可快速的引用公共的實時資產。對於此套能力體系,研發同學還是需要經歷相當多的研發過程,上圖示星的是我們希望能夠進行提效研發和縮短開發週期的環節,因此,我們推出了低程式碼研發和流批一體能力。
二、低程式碼研發
低程式碼主要解決我們實時開發中的兩個大的命題:研發提效和降低實時研發門檻,對於這兩個問題面向的使用者群體還不一樣。一類是資深的實時研發同學,他們比較瞭解實時研發中的各項細節,但是很多基礎性的程式碼研發工作會極大影響他們的效率;另一類則是實時的入門級選手,他們對於實時研發的概念和使用方式都不太熟悉,可能是對照著 API 一步步試錯。
對於這兩個風格不一樣的人群,他們本質的需求都是希望有個工具來解決他們的問題,由此我們構建了實時低程式碼研發能力。本著產品易用、任務易維護、程式碼正確的前提,我們透過配置化研發,將實時研發的正規化抽象,並整合高階的實時解決方案,最後期望能夠強化任務自動化運維,讓使用者在低程式碼中所配即所得,即配即上線。
我們優先從資料場景入手考慮低程式碼研發工具所需具備的能力。彙總計算場景中,側重對統計週期和維度的各種組合,而指標計算大部分是累加型(COUNT(1))、聚合型(SUM(xxx))和去重型(COUNT(DISTINCT xxx)),當然還需要具備簡單的邏輯過濾、維表關聯等基礎程式碼操作。標籤場景中,側重對明細資料的處理和解析,需要能夠支援各種實時計算運算元。特徵場景和指標計算場景很像,但是時間視窗多以滑窗為主,計算近 x 分鐘/小時的視窗聚合資料,維度主要是 user 或 item 粒度(如計算商品、流量點位、店鋪等),特徵中計算運算元較為豐富,且一個需求中需提供多個滑窗、多種指標的特徵,需要能夠支援多視窗多運算元的實時計算能力。
綜合以上三個場景,我們抽取三者共同的特點:運算元支援、Flink 特性封裝、批次研發
對於這麼多能力需求,我們採用維度建模的理論來進行構建,Flink 實時計算中三大 Connector(Source/Sink/Dim)和維度建模理論天然的契合,從明細事實表出發,進行一系列的資料操作,設定統計週期和維度,計算相應的實時指標。剩下就是對於低程式碼能力細節的拆解,從使用者體驗、平臺能力和引擎最佳化三個角度進行構建。
整個平臺能力分為使用者任務配置和程式碼邏輯生成兩大塊。
在使用者操作介面,我們定義了關聯維表、資料膨脹、表級去重、表級過濾四大過程元件,並透過計算檢視這個能力兜底以上運算元不能覆蓋的場景。同時定義統計週期和統計維度兩個結果元件,使用這兩個元件則預設是彙總指標計算,反之則是明細資料處理。對於這些元件中的資訊,我們抽象了計算元素的概念,將重要的元件內容和來源表繫結,一些通用的計算正規化和資產消費口徑,使用者可以直接選用其他使用者公共定義的邏輯,提高開發效率。
這樣透過新增元件,篩選維度和週期,對結果表中的欄位定義其型別,並選擇具體的邏輯,調整維度分佈後,便完成了實時任務的配置。
任務配置完,平臺側從結果表反向推導,判斷任務配置的邏輯是否正確,這一步很像 Flink 執行計劃生成的邏輯,從後向前不斷迴圈校驗各運算元的正確性,直至整個任務程式碼生成,這便完成了程式碼的編輯工作,使用者對物理任務進行執行計劃配置即可上線。
對於低程式碼研發中引擎的最佳化,我以實時特徵舉例。首先我們來對比下指標場景和特徵場景的異同點,其最主要的差異在於視窗和運算元的複雜度,同時特徵中多以使用者粒度也決定了下發資料相對較多,資料吞吐較高。
從以上這些現狀出發,我們對 Flink 的視窗計算做了一系列最佳化,首先從單滑窗升級到了多劃窗語義。根據下游使用橫表和豎表資料需求,將多滑窗中的視窗行轉列成多個指標,對資料進行拉橫,減少下游輸出的條數。
同時對觸發策略進行升級,可支援視窗觸發前後都能進行資料的更新,當然對於視窗觸發後主要用來進行資料置 0 的操作。對於定時更新的資料下發,考慮到下游的資料庫效能,對 Connector 加入了限流功能。還引入了對視窗狀態變更檢測能力,如果視窗內的資料沒有變更,也不需要進行下發更新。
對於多滑窗的狀態儲存最佳化,和 Flink 開源版本類似,加入了子窗的概念,一個資料保證其只劃分到最細粒度的視窗中,視窗計算時彙總各子窗中的資料即可完成資料聚合。
最後透過一個案例介紹實時低程式碼研發的使用
首先在來源表上定義計算元素,這些定義的邏輯可被過程和結果元件使用。配置皮膚中有三大塊:過程配置、結果元件和麵向結果表的欄位定義,對於不同統計週期的相同計算邏輯,可使用批次複製,修改統計週期即可。
平臺還提供了統計週期和維度的組合拆分能力,使用者根據統計週期和維度的資料情況,選擇是合併一個任務還是拆分多個任務。
最後便是生成的程式碼展示,這裡提到的是,平臺側會感知 UV 和 PV 的計算邏輯,並對 UV 類累計指標單獨拆成子任務計算,最後和 PV 類進行合併,使用者還能使用我們內建的累計去重計算方案。
三、流批一體
在構建流批能力之前,我們先 REVIEW 下當前實時數倉中的資料鏈路情況。Lambda 架構中,三個消費場景的實時離線資料融合方案還不統一,從資料側到應用側都有觸發流批資料融合的邏輯,但本質上還是流批模型欄位對齊的語義表達,下游便可實現欄位對齊邏輯。
其次在實時數倉中,大部分都是從 ODS/DWD 層直接計算累計結果,而離線數倉中,應用層資料大部分都是從輕度彙總層計算得到,在構建流批資料時需考慮這樣的差異,可能流和批表的對齊方式就是明細和彙總。
在頻繁的大促過程中,實時和離線任務存在著重複開發的問題。對於研發口徑一致性,實時離線報表指標對齊,都有著一定的挑戰。對此我們考慮多個方面,從欄位對齊到引擎的生態,再到研發運維效率,並參考業界流批計算的案例,最終選用 Flink 引擎來構建流批一體的研發能力。
透過一套資產、一套引擎、一份程式碼,完成流和批任務的研發,最終透過流批能力覆蓋實時離線重複開發和兜底的場景,提高研發運維效率。
螞蟻主流的實時研發引擎還是 Blink,對於透過 Flink 來構建流批研發能力,有很多的工作要做,我們規劃了五個大的時間節奏點
- 首先將開源 Flink 適配到螞蟻計算元件中,包括一些可插拔的元件,Connector 等,同時實時研發平臺還要對 Flink 新引擎進行相容,並對標 Blink 之前的體驗進行能力的升級。
- 接著我們對 Hybrid Source 進行的 SQL 化定義,對 SQL 語法和 DDL 引數進行設計,同時引入了多源元表的能力,多源元表是在單源元表基礎之上,對欄位進行對映。
- 第一版的多源元表只能進行簡單的欄位對映,但發現往往流批 Source 表會出現欄位不對齊、欄位語義不一致、欄位數量不相等的情況,這就引入了虛擬列和流批標識的能力,透過新增虛擬列,能夠將某一方沒有的欄位補齊,並在程式碼中透過流批標識顯式地對欄位進行處理。
- 接下來對 Flink 批引擎進行了落地,和流引擎一樣先完成了生態和平臺的適配,接著便是對 Flink 批的執行引數,資源分配,併發推斷等能特性進行除錯。
- 最後便是流批一體的能力的落地,在平臺側實現多源元表定義、程式碼翻譯和任務運維,目前正應用在大促場景。
流引擎和批引擎在落地的過程中有很多相同的工作量,這裡主要介紹批計算引擎的架構。
首先是排程層,螞蟻 Flink 的排程使用了原生的 K8S 排程,我們還在嘗試叢集排程模式,在 K8S 之上直接獲取機器資源,減少任務釋出上線的時間,同時能保證任務的穩定性。
在引擎這一層,Flink 研發運維同學做了很多的工作,從上往下看,首先對齊 Blink SQL 完成計算函式的新增,並最佳化了部分執行計劃推斷的邏輯。如一個源抽取了 ab 欄位,同樣的表抽取了 bc 欄位,則會對 source 表進行合併讀取。
在批引擎執行最佳化層面,對批計算中的併發度、CPU 和記憶體進行配置,Connector 的併發度根據資料量進行推斷,而執行中搭配 AdaptiveBatchScheduler 進行動態調整。對於 CPU 和記憶體,則根據不同的運算元型別進行設定。並對線上任務進行壓測,發現並最佳化 Flink 批在大資料量和計算壓力下的一些改進點,保證批任務的執行效能和穩定性。
Connector 層面則主要對齊 Blink 進行適配,考慮到批任務會在計算完成之後一次性同步會產生輸出洪峰,為了保護線上庫,設定限流是相當必要的,引擎側在 Connector 外掛中實現了限流的能力。
DataStream 引擎和運算元主要使用開源能力。最後在可插拔元件中,我們主要對 Shuffle 元件、排程元件和後端狀態進行了適配最佳化。批任務預設使用基於 TaskManager 本地磁碟的 Shuffle 方式,這種方式對本地磁碟的要求比較高,在上下游互動的時候存在依賴關係,我們引入了開源的 flink remote shuffle 元件,獨立部分 Shuffle 元件,實現計存分離的架構。
在計算平臺層面,對批任務的預編譯、除錯、提交、釋出、執行監控進行了支援,對於離線程式碼中的時間變數、任務引數進行解析翻譯。其中最重要的是將 Flink 批計算型別加入到離線排程引擎中,依賴 Odps 等其它的任務產出的資料,在排程執行是生成任務例項,並查詢具體的執行日誌。
對於流批表對齊的問題,我們來看以上兩個 CASE。在流和批都是明細的情況下,流和批的欄位含義不一致和不對齊是常見的,比如離線是否打標是 Y/N,實時打標 1/0。而對於流明細批匯總的場景,比如離線是算到使用者粒度的輕度彙總資料,對於 PV 這樣的欄位,實時肯定沒有的。
對於以上這類問題,一個方案是某一方進行資料的改造,保證兩側的資料欄位對齊,但是成本相當高。因此,我們設計了虛擬列欄位,對於某一方不存在的情況下,使用虛擬列標識,同時對流表和批表進行引數定義,這樣就能在程式碼中顯式的判斷和處理,以此來解決流批欄位不對齊的問題,在這樣的能力支撐下,即使流和批表欄位完全不一致的極端情況,也能進行特判和處理。
對齊來源表欄位之後,我們來看下流批一體的整體方案。舉個例子來簡述下具體的方案細節,有 stream_source 和 batch_source 兩個來源表,其中 c 和 d 欄位是不對齊的,透過虛擬列進行補充,註冊成 mix_source 的多源元表,我們在正常開發流批任務的時候,根據流批標識進行邏輯判斷,同時也能透過程式碼變數做流批的自定義邏輯。
平臺側會根據 mix_source 背後的單源元表進行物理程式碼的翻譯,同時透過一個 View 的適配,將欄位和虛擬列定義完成。批程式碼我們支援靜態分割槽,也就是在 DDL 中定義分割槽,和動態分割槽,在程式碼中顯示的指定時間變數,以此對離線分割槽進行裁剪。當然對於維表和結果表,當前只能支援單源或者欄位完全一致的多源,這塊目前沒有特別強的訴求,需要將維表和結果表也要支援不同的欄位定義。
對於長週期去重計算指標,如大屏場景對資料結果查詢效能有一定的要求,往往需要將資料計算到一個指標或者很小量級的資料,能夠快速的進行累加。
對於這類場景,在沒有應用 Hybrid Source 之前,我們通常的做法是藉助 Hbase 這樣的 KV 庫,儲存使用者的訪問狀態,資料過來是校驗使用者是否訪問過,最終算到天級的新增 UV 開窗累計即可。另一種方向則是直接在 Flink 中設定較大的狀態過期時間,相當於把外部儲存內建到引擎中,但此種方案需要考慮,如果在任務出現問題,狀態需要丟棄,或者中途修改邏輯的情況下,實時回刷成本很高。
對於以上兩個問題,我們設計透過 Hybrid Source 來支撐。Hybrid Source 也是使用多源元表,對映實時和離線欄位,我們定義了 Hybird Source SQL 的 DDL 語義,0 和 1 標識批和流表,同時定義了 fieldMappings 欄位來標識欄位名稱不對齊的情況,定義 virtualFields 表達虛擬列,在 Connector 外掛中根據這些定義和流批標識,對資料進行打標,實時任務即可完成 Hybrid Source 場景複雜 SQL 開發。右下角圖片是 Hybrid Source 任務發上線的啟動介面,對於批和流分別選擇啟動的時間。
讓我們看下這個流批一體的案例,需求是開發雙十一活動中的權益領取核銷情況,我們透過 Mix 元表定義了實時和離線明細表,在程式碼裡面顯式的處理了流和批不同的邏輯,實時側會對任務開始時間和延遲資料做處理,批則會限制排程日期的資料。
同時該任務開發了 Bitmap 的自定義函式,實時和離線共用一份 UDX 進行計算,最後分別對流和批元表進行引數配置,設定排程屬性後即可完成上線,上線後生成兩個任務,分別進行運維。
四、規劃展望
對於本次分享的低程式碼和流批一體能力,後續會不斷的擴充使用場景,將實時資料應用到更多有價值的地方。同時在實時研發提效和降低門檻這件事情上,會繼續往前走,後續兩個功能穩定且使用者積累一定程度後,會嘗試將能力進行整合,在低程式碼中實現一站式開發。最後則是看向業界都在探索的資料湖命題,希望能夠在幾個業務場景中將這套較大的解決方案落地。
更多內容
活動推薦
阿里雲基於 Apache Flink 構建的企業級產品-實時計算 Flink 版現開啟活動:
0 元試用 實時計算 Flink 版(5000CU*小時,3 個月內)
瞭解活動詳情:https://free.aliyun.com/?pipCode=sc