螞蟻實時低程式碼研發和流批一體的應用實踐

ApacheFlink發表於2023-05-16

摘要:本文整理自螞蟻實時數倉架構師馬年聖,在 Flink Forward Asia 2022 流批一體專場的分享。本篇內容主要分為四個部分:

  1. 實時應用場景與研發體系
  2. 低程式碼研發
  3. 流批一體
  4. 規劃展望

點選檢視原文影片 & 演講PPT

一、實時應用場景與研發體系

1

螞蟻實時的資料應用主要包括報表監控、實時標籤和實時特徵三部分。最底層的實時資料採集來源於線上日誌、實時訊息和資料庫日誌三大塊,並由此構建了實時和離線的明細中間層,該中間層定義不同的主題域,如:流量、營銷、交易等。再往上構建應用層資料去支撐前臺業務的實時資料需求。

在這三個應用場景中,報表場景根據查詢特性的不同,實時資料會被儲存到 OLAP 引擎或 KV 庫,在應用層進行實時/離線資料的融合,來構建實時資料包表;而在實時標籤場景,將實時資料直寫到 Hbase/Lindorm 庫中,離線資料透過標籤平臺迴流至線上庫中;特徵場景和標籤場景鏈路類似,透過特徵檢視對流/批資料分別進行欄位 Mapping。

以上的資料鏈路架構在研發、運維、消費的成本上均存在一定的問題,在開發階段,首先突出的是實時研發的效率問題,一個實時任務從需求對接到資料交付往往需要較長時間,如果涉及到離線回補邏輯,則還需開發離線兜底鏈路,並同步離線資料到線上庫中;在線上運維階段,雖然 Flink 一直在降低任務調優難度,但實時離線計算引擎的運維壓力是雙重的,往往需要互相翻譯口徑進行問題排查;在消費鏈路中,實時離線兩撥同學研發,往往報表會配置兩份,其工作量重複之餘,也會增加下游的資料使用成本。

最後再丟擲一個實時中的老大難問題:長週期計算問題。支付寶大促活動頻繁,計算活動期間累計去重 UV 這類指標,研發運維成本一直較高,這也是我們嘗試在最佳化解決的問題。

2

螞蟻實時研發體系在去年完成了的升級,構建了基於實時元表為載體的實時研發能力,從實時資產的定義、到實時程式碼研發、到線上的實時質量監控,再到實時後設資料消費,都是基於元表來完成的,在資料研發時可快速的引用公共的實時資產。對於此套能力體系,研發同學還是需要經歷相當多的研發過程,上圖示星的是我們希望能夠進行提效研發和縮短開發週期的環節,因此,我們推出了低程式碼研發和流批一體能力。

二、低程式碼研發

3

低程式碼主要解決我們實時開發中的兩個大的命題:研發提效和降低實時研發門檻,對於這兩個問題面向的使用者群體還不一樣。一類是資深的實時研發同學,他們比較瞭解實時研發中的各項細節,但是很多基礎性的程式碼研發工作會極大影響他們的效率;另一類則是實時的入門級選手,他們對於實時研發的概念和使用方式都不太熟悉,可能是對照著 API 一步步試錯。

對於這兩個風格不一樣的人群,他們本質的需求都是希望有個工具來解決他們的問題,由此我們構建了實時低程式碼研發能力。本著產品易用、任務易維護、程式碼正確的前提,我們透過配置化研發,將實時研發的正規化抽象,並整合高階的實時解決方案,最後期望能夠強化任務自動化運維,讓使用者在低程式碼中所配即所得,即配即上線。

4

我們優先從資料場景入手考慮低程式碼研發工具所需具備的能力。彙總計算場景中,側重對統計週期和維度的各種組合,而指標計算大部分是累加型(COUNT(1))、聚合型(SUM(xxx))和去重型(COUNT(DISTINCT xxx)),當然還需要具備簡單的邏輯過濾、維表關聯等基礎程式碼操作。標籤場景中,側重對明細資料的處理和解析,需要能夠支援各種實時計算運算元。特徵場景和指標計算場景很像,但是時間視窗多以滑窗為主,計算近 x 分鐘/小時的視窗聚合資料,維度主要是 user 或 item 粒度(如計算商品、流量點位、店鋪等),特徵中計算運算元較為豐富,且一個需求中需提供多個滑窗、多種指標的特徵,需要能夠支援多視窗多運算元的實時計算能力。

綜合以上三個場景,我們抽取三者共同的特點:運算元支援、Flink 特性封裝、批次研發

對於這麼多能力需求,我們採用維度建模的理論來進行構建,Flink 實時計算中三大 Connector(Source/Sink/Dim)和維度建模理論天然的契合,從明細事實表出發,進行一系列的資料操作,設定統計週期和維度,計算相應的實時指標。剩下就是對於低程式碼能力細節的拆解,從使用者體驗、平臺能力和引擎最佳化三個角度進行構建。

5

整個平臺能力分為使用者任務配置和程式碼邏輯生成兩大塊。

使用者操作介面,我們定義了關聯維表、資料膨脹、表級去重、表級過濾四大過程元件,並透過計算檢視這個能力兜底以上運算元不能覆蓋的場景。同時定義統計週期和統計維度兩個結果元件,使用這兩個元件則預設是彙總指標計算,反之則是明細資料處理。對於這些元件中的資訊,我們抽象了計算元素的概念,將重要的元件內容和來源表繫結,一些通用的計算正規化和資產消費口徑,使用者可以直接選用其他使用者公共定義的邏輯,提高開發效率。

這樣透過新增元件,篩選維度和週期,對結果表中的欄位定義其型別,並選擇具體的邏輯,調整維度分佈後,便完成了實時任務的配置。

任務配置完,平臺側從結果表反向推導,判斷任務配置的邏輯是否正確,這一步很像 Flink 執行計劃生成的邏輯,從後向前不斷迴圈校驗各運算元的正確性,直至整個任務程式碼生成,這便完成了程式碼的編輯工作,使用者對物理任務進行執行計劃配置即可上線。

6

對於低程式碼研發中引擎的最佳化,我以實時特徵舉例。首先我們來對比下指標場景和特徵場景的異同點,其最主要的差異在於視窗和運算元的複雜度,同時特徵中多以使用者粒度也決定了下發資料相對較多,資料吞吐較高

從以上這些現狀出發,我們對 Flink 的視窗計算做了一系列最佳化,首先從單滑窗升級到了多劃窗語義。根據下游使用橫表和豎表資料需求,將多滑窗中的視窗行轉列成多個指標,對資料進行拉橫,減少下游輸出的條數。

同時對觸發策略進行升級,可支援視窗觸發前後都能進行資料的更新,當然對於視窗觸發後主要用來進行資料置 0 的操作。對於定時更新的資料下發,考慮到下游的資料庫效能,對 Connector 加入了限流功能。還引入了對視窗狀態變更檢測能力,如果視窗內的資料沒有變更,也不需要進行下發更新。

對於多滑窗的狀態儲存最佳化,和 Flink 開源版本類似,加入了子窗的概念,一個資料保證其只劃分到最細粒度的視窗中,視窗計算時彙總各子窗中的資料即可完成資料聚合。

圖片

最後透過一個案例介紹實時低程式碼研發的使用

首先在來源表上定義計算元素,這些定義的邏輯可被過程和結果元件使用。配置皮膚中有三大塊:過程配置、結果元件和麵向結果表的欄位定義,對於不同統計週期的相同計算邏輯,可使用批次複製,修改統計週期即可。

平臺還提供了統計週期和維度的組合拆分能力,使用者根據統計週期和維度的資料情況,選擇是合併一個任務還是拆分多個任務。

最後便是生成的程式碼展示,這裡提到的是,平臺側會感知 UV 和 PV 的計算邏輯,並對 UV 類累計指標單獨拆成子任務計算,最後和 PV 類進行合併,使用者還能使用我們內建的累計去重計算方案。

三、流批一體

7

在構建流批能力之前,我們先 REVIEW 下當前實時數倉中的資料鏈路情況。Lambda 架構中,三個消費場景的實時離線資料融合方案還不統一,從資料側到應用側都有觸發流批資料融合的邏輯,但本質上還是流批模型欄位對齊的語義表達,下游便可實現欄位對齊邏輯。

其次在實時數倉中,大部分都是從 ODS/DWD 層直接計算累計結果,而離線數倉中,應用層資料大部分都是從輕度彙總層計算得到,在構建流批資料時需考慮這樣的差異,可能流和批表的對齊方式就是明細和彙總。

8

在頻繁的大促過程中,實時和離線任務存在著重複開發的問題。對於研發口徑一致性,實時離線報表指標對齊,都有著一定的挑戰。對此我們考慮多個方面,從欄位對齊到引擎的生態,再到研發運維效率,並參考業界流批計算的案例,最終選用 Flink 引擎來構建流批一體的研發能力。

透過一套資產、一套引擎、一份程式碼,完成流和批任務的研發,最終透過流批能力覆蓋實時離線重複開發和兜底的場景,提高研發運維效率。

9

螞蟻主流的實時研發引擎還是 Blink,對於透過 Flink 來構建流批研發能力,有很多的工作要做,我們規劃了五個大的時間節奏點

  1. 首先將開源 Flink 適配到螞蟻計算元件中,包括一些可插拔的元件,Connector 等,同時實時研發平臺還要對 Flink 新引擎進行相容,並對標 Blink 之前的體驗進行能力的升級。
  2. 接著我們對 Hybrid Source 進行的 SQL 化定義,對 SQL 語法和 DDL 引數進行設計,同時引入了多源元表的能力,多源元表是在單源元表基礎之上,對欄位進行對映。
  3. 第一版的多源元表只能進行簡單的欄位對映,但發現往往流批 Source 表會出現欄位不對齊、欄位語義不一致、欄位數量不相等的情況,這就引入了虛擬列和流批標識的能力,透過新增虛擬列,能夠將某一方沒有的欄位補齊,並在程式碼中透過流批標識顯式地對欄位進行處理。
  4. 接下來對 Flink 批引擎進行了落地,和流引擎一樣先完成了生態和平臺的適配,接著便是對 Flink 批的執行引數,資源分配,併發推斷等能特性進行除錯。
  5. 最後便是流批一體的能力的落地,在平臺側實現多源元表定義、程式碼翻譯和任務運維,目前正應用在大促場景。

10

流引擎和批引擎在落地的過程中有很多相同的工作量,這裡主要介紹批計算引擎的架構。

首先是排程層,螞蟻 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 等其它的任務產出的資料,在排程執行是生成任務例項,並查詢具體的執行日誌。

11

對於流批表對齊的問題,我們來看以上兩個 CASE。在流和批都是明細的情況下,流和批的欄位含義不一致和不對齊是常見的,比如離線是否打標是 Y/N,實時打標 1/0。而對於流明細批匯總的場景,比如離線是算到使用者粒度的輕度彙總資料,對於 PV 這樣的欄位,實時肯定沒有的。

對於以上這類問題,一個方案是某一方進行資料的改造,保證兩側的資料欄位對齊,但是成本相當高。因此,我們設計了虛擬列欄位,對於某一方不存在的情況下,使用虛擬列標識,同時對流表和批表進行引數定義,這樣就能在程式碼中顯式的判斷和處理,以此來解決流批欄位不對齊的問題,在這樣的能力支撐下,即使流和批表欄位完全不一致的極端情況,也能進行特判和處理。

12

對齊來源表欄位之後,我們來看下流批一體的整體方案。舉個例子來簡述下具體的方案細節,有 stream_source 和 batch_source 兩個來源表,其中 c 和 d 欄位是不對齊的,透過虛擬列進行補充,註冊成 mix_source 的多源元表,我們在正常開發流批任務的時候,根據流批標識進行邏輯判斷,同時也能透過程式碼變數做流批的自定義邏輯。

平臺側會根據 mix_source 背後的單源元表進行物理程式碼的翻譯,同時透過一個 View 的適配,將欄位和虛擬列定義完成。批程式碼我們支援靜態分割槽,也就是在 DDL 中定義分割槽,和動態分割槽,在程式碼中顯示的指定時間變數,以此對離線分割槽進行裁剪。當然對於維表和結果表,當前只能支援單源或者欄位完全一致的多源,這塊目前沒有特別強的訴求,需要將維表和結果表也要支援不同的欄位定義。

13

對於長週期去重計算指標,如大屏場景對資料結果查詢效能有一定的要求,往往需要將資料計算到一個指標或者很小量級的資料,能夠快速的進行累加。

對於這類場景,在沒有應用 Hybrid Source 之前,我們通常的做法是藉助 Hbase 這樣的 KV 庫,儲存使用者的訪問狀態,資料過來是校驗使用者是否訪問過,最終算到天級的新增 UV 開窗累計即可。另一種方向則是直接在 Flink 中設定較大的狀態過期時間,相當於把外部儲存內建到引擎中,但此種方案需要考慮,如果在任務出現問題,狀態需要丟棄,或者中途修改邏輯的情況下,實時回刷成本很高。

對於以上兩個問題,我們設計透過 Hybrid Source 來支撐。Hybrid Source 也是使用多源元表,對映實時和離線欄位,我們定義了 Hybird Source SQL 的 DDL 語義,0 和 1 標識批和流表,同時定義了 fieldMappings 欄位來標識欄位名稱不對齊的情況,定義 virtualFields 表達虛擬列,在 Connector 外掛中根據這些定義和流批標識,對資料進行打標,實時任務即可完成 Hybrid Source 場景複雜 SQL 開發。右下角圖片是 Hybrid Source 任務發上線的啟動介面,對於批和流分別選擇啟動的時間。

14

讓我們看下這個流批一體的案例,需求是開發雙十一活動中的權益領取核銷情況,我們透過 Mix 元表定義了實時和離線明細表,在程式碼裡面顯式的處理了流和批不同的邏輯,實時側會對任務開始時間和延遲資料做處理,批則會限制排程日期的資料。

同時該任務開發了 Bitmap 的自定義函式,實時和離線共用一份 UDX 進行計算,最後分別對流和批元表進行引數配置,設定排程屬性後即可完成上線,上線後生成兩個任務,分別進行運維。

四、規劃展望

對於本次分享的低程式碼和流批一體能力,後續會不斷的擴充使用場景,將實時資料應用到更多有價值的地方。同時在實時研發提效和降低門檻這件事情上,會繼續往前走,後續兩個功能穩定且使用者積累一定程度後,會嘗試將能力進行整合,在低程式碼中實現一站式開發。最後則是看向業界都在探索的資料湖命題,希望能夠在幾個業務場景中將這套較大的解決方案落地。

點選檢視原文影片 & 演講PPT


更多內容


活動推薦

阿里雲基於 Apache Flink 構建的企業級產品-實時計算 Flink 版現開啟活動:
0 元試用 實時計算 Flink 版(5000CU*小時,3 個月內)
瞭解活動詳情:https://free.aliyun.com/?pipCode=sc

image.png

相關文章