1. 程式人生 > 其它 >騰訊新聞基於 Flink PipeLine 模式的實踐

騰訊新聞基於 Flink PipeLine 模式的實踐

基於騰訊雲流計算Oceanus和PipeLine搭建的實時資料倉庫思想

摘要 :隨著社會消費模式以及經濟形態的發展變化,將催生新的商業模式。騰訊新聞作為一款集遊戲、教育、電商等一體的新聞資訊平臺、服務億萬使用者,業務應用多、資料量大。加之業務增長、場景更加複雜,業務對實時計算高可靠、可監控、低延時、資料可回溯的要求也越來越迫切。比如新聞廣告投放、停單、線上推薦、電商搜尋中,更快的響應使用者需求、精準計費停單,意味著著更好的使用者體驗和更多的收入。

接下來我們將介紹基於騰訊雲流計算 Oceanus Flink 平臺、PipeLine 設計模式搭建的實時資料倉庫思想。該方案已經落地內容商業化新聞如廣告實時廣告停單、實時報表、實時特徵計算、遊戲聯執行為分析、資料異常檢測等場景。

一、設計背景

目前商業化資料主要承擔了騰訊新聞客戶端、體育、新聞外掛、創新等業務的收入、廣告資料的採集、處理、計算分析工作。在資料上報規範化、資料的準確性、資料的高質量、系統高可用性、開發成本與效率等方面做了很多工作。

伴隨著騰訊新聞商業化業務增長,原先採用自行搭建的 Storm 叢集,運維成本高、擴容等極為不方便、經常出現效能不足等問題;加之業務對實時性要求和邏輯複雜度的提高, Storm 在開發靈活性、低延時、擴充套件性難以滿足現有的應用場景。

在此背景下,決定將原實時計算遷移至公司流計算 Oceanus Flink 平臺並進行程式碼重構,搭建一套靈活通用的實時資料倉庫,以支援團隊在多業務場景的快速發展。

0-1搭建新聞商業化實時數倉,面臨如下些挑戰:

1、遷移複雜:程式碼複用少、新系統與原資料核對需要保證線上業務邏輯不變情況下平穩切換新的數倉;

2、需求多複雜:騰訊新聞商業化資料僅廣告請求事件資料量高達幾百億/天,需求方有後臺、搜尋/推薦演算法組以及運營決策方等,需要快速接入流式引擎參與實時分析;

3、資料質量:業務的重要性決定了系統需要具備很高的可用性,資料質量必須穩定、抗風險,程式碼靈活複用、低耦合等;

4、數倉資料利用率:需設計足以支撐下游需求的中間數倉儲存層,下游新建一個任務,就需要消費一份與原始資料數量一致的資料造成計算資源極大的消耗,因此數倉的資料分層管理尤為迫切。

二、調研&技術選型

為解決以上面臨問題,我們在開發之前對資料倉庫相關技術進行調研給出了基本的對比情況,同時圍繞 Flink 生態總結近幾年業界在生產與應用中的實踐。

資料倉庫架構對比:

在大資料處理中,常見的資料倉庫架構有兩種:Lambda 架構和 Kappa 架構。如上表分析 lambda 和 Kappa 兩種數倉架構在多個維度各有利弊。在架構選擇上,結合 Lambda 架構在靈活度、成熟度、遷移成本表現優異特點以及騰訊新聞商業化資料已有業務特點,選擇 Lambda 架構。

訊息中介軟體對比:

Tube MQ 和 Hippo MQ 為騰訊大資料平臺(Tdbank)開發面向高吞吐高效能的分散式訊息中介軟體,TubeMQ 資料時延低,請求 TPS 高,擁有更好對外服務能力,支援客戶端過濾消費,目前 Tdbank 是公司統一的傳輸通道,故這裡我們選擇 TubeMQ 作為接入/接出的訊息佇列元件。

實時計算引擎對比:

在實時計算引擎選型上對比幾款開源。其中 Spark Streaming 利用微批處理模擬實時處理、在低延遲、複雜狀態管理、流處理等方面表現欠佳。Storm 各大公司陸續淘汰。而 Flink 就是為流式計算而生的,具備低延遲、狀態管理、高靈活度等特點。我們決定採用 Flink 作為實時計算引擎。另外、依託公司流計算 Oceanus 團隊提供的 Flink 平臺服務能夠實現應用部署、叢集管理等快速接入,並提供穩定的運維服務。

在實時數倉建設過程中,計算引擎的選型極為重要關係到後期能滿足多少業務需求、能夠實現何種複雜的功能,為了進一步瞭解Flink在業界各大公司的應用情況,我們對電商:淘寶天貓、京東、Shopee、唯品會;內容資訊:位元組跳動、騰訊、微博、Netflix、小紅書;短視訊/直播:抖音、快手、嗶哩嗶哩各行應用場景進行了總結。

概括其實踐6大場景分別為實時數倉、實時大屏、實時報表、實時監控、實時風控、線上學習,可以看出 Flink 已經成為未來流批計算引擎的趨勢。

三、商業化資料倉庫整體業務架構

正如第二章節所述我們面諸多問題和難點,需要一套行之有效的資料組織、管理和處理方法來讓我們的資料體系更加有序,使得下游接入使用成本最低、開發效率最高。下圖是整個商業化資料倉庫業務架構:

採集層使用大同、Boss 是資料採集上報服務,其中大同以成為集團資料治理力推的客戶端上報平臺,具備統一事件管理、統一引數規範上報,告別了以往上報需求散亂、上報不規範、資料難校驗。當一個使用者請求一個業務時,採集 SDK 會根據定義的上報規範將資料分發送到 Tube 供下游實時消費。

計算層提供實時和離線數倉兩部分,離線數倉是基於 TDW、HDFS 建立的各個業務請求、曝光、點選等維度的數倉表,利用尤拉平臺的資料分層、資料分類、資料血緣等能力完成資料資產的管理。實時數倉,正如第一章節所述設計的目的是解決需求多變、程式碼複用、系統高可用、海量資料低延時接入、資料高複用等問題,在 ODS 層(原始資料層)、DWD 層(資料明細層)、DWS 層(主題輕度資料彙總層)我們採用 TubeMQ 作為資料分發與快取,TubeMQ 解決了海量資料的即時接入問題。

在資料利用率上我們採用:

1、不同業務差異大的需求開發申請新的 Tube 消費節點;

2、功能差異不大且資料來源相同則通過 Flink 側流方式複製流。

資料在各層由流式計算引擎進行業務清洗和轉化的結果寫回至訊息佇列中,供下游使用。對於 ODS 層的實時資料每隔1小時同步一份至 TDW 儲存週期約3天,這份資料既能用於離線計算又能作為資料的備份鏈路異常時的問題排查和資料恢復。

儲存層使用的元件比較豐富,有 Impala、Clickhouse 秒級響應多維 OLAP 資料分析查詢的燈塔、人群投放系統,以及 MySQL 應用 OLTP 聯機事務處理的應用場景。值得注意是 Flink 直接寫 Redis 無法保障資料原子性,為此在寫入 Redis 之前通過 Hash 對 key 分組、引入重試佇列保障 Redis 讀寫穩定性。

監控、測試、管理模組,設計目的:

1、以往只能事後看日誌定位問題,計算引擎程式碼執行異常存在監控盲區,引入一套自定義錯誤碼和異常等級機制,一旦程式碼執行異常 StackTrace、錯誤碼、異常位置等通過企業微信及時通知負責人;

2、任務引數分優先順序管理,使得計算資源、系統引數等能夠靈活配置,抽象模組程式碼複用性更強;

3、為了提高開發進度及時驗證程式碼邏輯,巧妙搭建了一套抓取/解析 Tube 流資料位元組碼本地除錯工具,使得本地除錯程式碼邏輯與線上執行環境高度一致性。

總之,數倉的建設就是需要對 ODS 層資料進行 ETL,生成向 DWD 明細層(明細資料)及 DWS 服務層(主題輕度彙總資料)資料,DWD 及 DWS 兩層資料也很好地解決了中間表的複用問題。接下來我們對解決方案、實時數倉詳細設計進行介紹。

四、詳細設計方案&技術挑戰介紹

眾所周知實時數倉建設的難點在於如何設計一條高效能、高可用、低成本以及靈活度高的數倉鏈路。如下圖所示為我們的實時數倉架構:

儲存與接入層負責將客戶端、後臺、實時計算中間資料上報至訊息中介軟體 TubeMQ。TubeMQ 一方面負責實時資料的儲存,一方面承擔資料分發給離線/線上處理平臺的功能,同時構建資料來源與資料處理系統之間的橋樑。其中 DWD 層的設計目的是減少下游頻繁重複消費 ODS 層原始資料,對於新需求的開發,我們只需要申請 DWD 層的 TubeMQ 新消費節點即可,極大的節省計算資源。計算層主要負責資料的 ETL、維表關聯、特徵抽取等業務邏輯的計算。資料倉庫儲存採用 TDW、HDFS 和 Impala,ODS 層的原始資料預設儲存在 HDFS 上,儲存週期一般3天,目的是方便問題排查及資料備份回滾;DWD 和 DWS 層資料支援寫入 TDW、HDFS 用於離線計算,同時支援寫入 Impala 供應用層直接使用。

正如文章開篇所提,新聞商業化資料開發面臨業務需求複雜、開發週期短,系統要求高可用、低延時等問題。提出的主要解決方案有以下幾點:

  • 採用 Pipeline 模式管道式程式設計,元件模組化封裝;
  • 任務及系統引數按優先順序配置輸入,使得程式碼與配置高度解耦;
  • 在程式碼層面的監控我們自定義了一套錯誤碼,利用 Try{}Catch{} 捕獲程式碼異常,報警至企業微信群實現異常實時告警;
  • 廣播流方式實現配置資料動態更新,無需重啟任務;
  • 通過側流等方式支援多種流計算模式: 單流、多流混合, 流複製,流切分分流;
  • 利用 Hash 分組、異常佇列重試、Batch 寫入重試機制等保證資料原子性、資料儲存不丟失;

接下來我們將一一介紹。

五、實時數倉之計算引擎 PipeLine 模式管道設計

PipeLine 為自定義管道流水線,可以將任務的處理分解為若干個處理階段,即前一個處理單元的結果也是第二個模組的輸入,實現計算作業流水線化。引入 PipeLine 設計模式思想可以充分利用 Flink 資源提高計算效率,使得程式碼結構層次更加清晰、程式碼解耦、模組高複用成為可能。

介紹專案中使用比較多的一個 PipeLine 模型。

從時序圖可以看出,該 PipeLine 完整的執行流程:Conf->Init->Process->Sideout->Monitor->Sink,六步組成一個閉環;Conf 負責對任務引數按優先順序解析;Init 初始化當前處理任務,完成 Flink 啟動前環境準備流資料的接入;Process 為核心的功能處理介面,接收前一個處理階段的輸入流,並按業務邏輯完成計算將結果輸入到下一個階段;Sideout 基於 Flink 側輸出功能,可實現流的複製、篩選、過濾等操作;Monitor 為任務監控介面,開發時可選擇實現;Sink 完成流的輸出,如寫入 Redis、Clickhouse、Tube 等。最後通過 pipeline.execute() 啟動流的計算。

我們再來看該 PipeLine 類圖,BaseProcedure 為全域性介面,所有 PipeLine 流程上的類或介面都需要繼承,BaseProcedure 完成兩部分工作即 setConfig() 全域性任務引數設定和 checkConfig() 在啟動任務之前完成所有引數校驗。這種設計的好處是引數全域性化,避免參數配置錯誤或遺漏造成實時任務上線後異常。

結合管道示意圖,執行流程可以拆封若干管道,每個管道為互相隔離的功能模組,管道與管道之間做了資料型別探測,支援“無縫連線”。我們通過側流輸出的方式實現流的複製,使得在一個計算任務中可以滿足多個需求開發。另外對於複雜需求無法通過一個主處理邏輯一步實現,我們支援將主處理邏輯資料接入到使用者自定製化處理邏輯模組進行處理。

Flink PipeLine 最大的價值在於為開發者統一了實時計算輸入輸出格式,使用者只需要關心 Process 中的邏輯即可。此外,PipeLine 將整個流計算步驟化,使得複雜任務新增、移除、替換模組變的非常輕鬆,而且本地除錯只需要替換 Init、Sink 邏輯,確保了線上與線下程式碼 Process 中邏輯一致。

另外日常常用的功能我們也進行了封裝,有基礎的流資料讀寫、流的操作、監控告警、日期處理、檔案處理等。

最後通過一個應用案例來感受下 PipeLine 程式設計模式,如何提高程式碼的可讀性和複用性。左圖程式碼功能包括:輸入源相關引數的配置;引數全域性化,獲取輸入資料來源,流的複製,以及業務邏輯四個計算步驟。可以看到理解該虛擬碼功能非常依賴程式碼註釋,如果需要新增一條複製流,則深入原始碼中進行修改,極容易動一發而牽全身引發線上事故。對比右圖 PipeLIne 程式碼,可以發現,任務步驟清晰、模組解耦強、功能增刪簡單。

總結概括 Flink + PipeLine 模式有四個主要特點:

1、模組複用率極大提高,不同同學在使用專案程式碼時,無需關心程式碼中的邏輯,只需要知道模組輸入輸出是什麼,完成了什麼功能;

2、通過 PipeLine 模式將資料處理過程固化為若干步驟,使得程式設計靈活,程式碼可讀性增強;

3、利用側流技術極大的流的複用性,一個計算任務可以完成不同業務需求,無需重複申請新的訊息中介軟體消費節點和新建 Flink 任務;

4、測試中只需要替換 PipeLine 的輸入輸出,即 Init 和 Sink 為本地測試模組。

六、高可用及穩定性設計

實時數倉設計最重要的是保證系統的高可用,一旦發生故障,即使是很短時間的中斷,都會影響業務運營。

眾所周知,業界在提高系統可靠性和穩定性常用方法比如有,冗餘備份、流量熔斷機制、容錯機制、故障自動恢復、監控等。對於我們設計的系統,一方面依託流計算 Oceanus 平臺提供的指標告警、指標監控以及 SLA 保障等強大能力。另一方在設計上通過捕獲程式碼異常,分級告警;引數分層管理、引數廣播動態更新;重試機制;以及高效的本地測試等方法提高系統可靠性。

6.1 程式碼異常捕獲、分級告警

實時計算模組眾多,會因為上游資料格式上報出錯、程式碼 Bug、資料庫連線異常等引起計算出錯甚至造成任務中斷,設計的系統必須具備監控上報和告警的能力。監控報警任務為獨立任務,而各個業務的任務通過 Try{}Catch(Exception e){} 方式捕獲 Task 中程式碼異常,將報警資訊統一發送到同一個訊息中介軟體,監控報警任務將接收的資料進行 Hash(level,project name,type) 編碼,通過 TimeWindow、Aggregate 聚合使得相同錯誤的資料聚合在一起,減少報警疲勞。

另外我們將錯誤分為三個等級:ERROR(錯誤)、WARN(警告)、INFO(提示資訊),並總結了49種常見的報警錯誤碼,比如:資料庫連線異常、流量抖動異常等。實踐證明一旦系統出現問題,這種程式碼層的監控設計能夠及時發現告警,從而縮短系統的故障時間,解決原 Strom 系統程式碼監控盲區。

6.2任務引數優先順序管理

一個實時計算任務少則有幾十個外部配置引數,有任務私有引數,有專案功能引數,也有涉密引數。為此我們定義了4層任務引數配置優先順序:流計算 Oceanus平臺配置>七彩石>各模組下的.properties > base.properties。引數優先順序管理給整個專案。這種設計總結有以下幾點好處:

1、配置靈活度高;

2、程式碼與引數解耦;

3、保密性強;

6.3 引數配置動態更新

在使用 Flink 流式計算時,程式碼功能實現重要的同時,後期的可維護性一樣很重要。任務中執行過程中,經常需要更新引數重啟任務,比如實時計算過程中,源表突然增加一個欄位。為此我們把配置資訊廣播流化,將生成廣播狀態流和資料流進行 Connect。廣播流的是否需要傳送通過定時任務檢查配置版本有無變動。該方法減少了系統因頻繁重啟造成的資料延遲。

6.4高效的本地測試

本地測試通過根據訊息主題,從線上獲取真實的位元組碼資料,替換 Init 介面的輸入源, Process 主邏輯無需為本地除錯做任何改動,使得線上、測試程式碼和環境高度一致,本地列印輸出,結果資料直觀展示。極大的提高了開發效率,縮短了問題定位時間。

6.5 重試機制

資料與儲存介質之間互動常常會由於連線、網路抖動等問題造成資料的讀寫失敗,對於一些較為苛刻的場景,如交易資料分析、實時推薦特徵、負反饋計算,需要資料讀寫零的丟失。為此我們為 Redis、Mysql 等寫資料設計一套重試機制。

上游 Operator 傳輸的資料首先快取在 Flink 分散式阻塞佇列快取池中,等待檢查重試機制中的快取 Queue 是否有待重試資料,我們的策略是優先輸出 Queue 中資料,待所有資料重試完才操作寫本次 Operator 傳送來的資料。如果資料超過重試次數上限或者重試 Queue 容量上限將出發告警,本條資料將會丟棄。同時通過引入 Java8函數語言程式設計方式完成自定義的輸出函式,從而提高編碼效率,以實現重試機制程式碼的高複用性。

最後以實時特徵計算寫 Redis 為例,展示重試機制的應用如何保障資料0丟失。該應用由四部分組成:各個業務輸入資料來源模組。Flink實時特徵計算模組,各個業務單獨實現資料解析和特徵抽取 Flink 任務,通過重試機制模組寫入同一個訊息中介軟體;下游為同一個 Flink 特徵構造任務主要完成 Protobuf 資料構造,利用業務標識欄位區分接收訊息中間中的混合業務特徵資料,從而發到不同的 Redis 中。這個思想使用很多,比如 Mysql、Clickhouse、Http 等的 Sink。

七、總結展望

經過此次實時數倉改造及計算任務遷移,系統達到了 SLA 標準。利用 PipeLine 模式、流複製、引數分層管理等手段提升資料採集的可靠性和及時性,提高了程式碼資料質量,開發效率得到了極大提升,計算和儲存資源得到充分利用。未來我們將基於流計算 Oceanus 平臺強大能力在線上學習、搜尋、人群畫像等進行探索和應用。

流計算 Oceanus限量秒殺專享活動火爆進行中↓↓

關注“騰訊雲大資料”公眾號,技術交流、最新活動、服務專享一站Get~