Flink 在快手的持續優化與實踐

分享嘉賓:董亭亭 @快手

內容來源:Flink 中文社區

導讀**:**本文由快手實時計算負責人董亭亭分享,主要介紹快手基於 Flink 的持續優化與實踐。內容包括:

01

Flink 穩定性持續優化

第一部分是 Flink 穩定性的持續優化。該部分包括兩個方面,第一個方面,主要介紹快手在 Flink Kafka Connector 方面做的一些高可用,是基於內部的雙機房讀或雙機房寫和一些容錯的策略。第二部分關於 Flink 任務的故障恢復。我們在加速故障恢復方面做了一些優化工作。

 

首先,介紹 Source 方面的高可用。在公司內部比較重要的數據寫 Kafka 時,Kafka  層面爲保障高可用一般都會創建雙集羣的 topic。雙集羣的 topic 共同承擔全部流量,如果單集羣發生故障,上游自動分流。Kafka 層面通過這種方式做到雙集羣的高可用。但是 Flink 任務在消費雙集羣 topic 時,本身是不能做到高可用的。Flink 任務通過兩個 Source union 方式消費,Source 分別感知上游 topic 故障,單集羣故障需手動將故障 Source 摘除。這種方式的缺點是故障時需要人工的干預,必須手動去修改代碼的邏輯,程序內部本身是不能做到高可用的。這是做雙機房讀的背景。

 

爲了解決上述問題,我們封裝了一個 Kafka 的 Cluster Source,它在 API 上支持讀取雙集羣的 topic。同時做到,可以容忍單集羣故障,集羣故障恢復時也可以自動將故障集羣重新加入。

 

接下來是關於 Sink 方面的高可用。Flink 寫雙集羣 Kafka topic,會定義不同集羣  Sink,邏輯內控制拆流。這種方式靈活性差,且不能容忍單機房故障。如果單集羣發生故障,仍需要手動摘除對應的 Sink。

 

同樣,針對 sink 我們也定製了一個 Cluster Sink,它 API 上支持寫雙集羣 topic。具體寫的策略,可以支持輪詢和主從寫的方式。如果單集羣發生故障,邏輯內會自動將流量切到正常集羣 topic。如果單集羣故障恢復之後,也能感知到集羣的恢復,可以自動的再把相應集羣恢復回來。

 

另外,基於 Kafka 的 connector,我們也做了一些容錯的策略,這裏提到三點。

 

第二部分是 Flink 任務的故障恢復優化,分爲兩個過程。一個是故障發現,另外一個是故障恢復。實際的生產環境中,一些不穩定的因素會導致故障恢復的時間特別的長,用戶的感知會比較差。同時,內部也有一些比較高優的任務,它對穩定性的要求比較高。我們希望做一些事情,把整個故障恢復的時間儘可能縮短。我們定了一個優化目標,20 秒內做到一個自動的恢復。

在故障發現階段的優化包括三點:

在故障恢復階段的優化包括:

02

Flink 任務啓動優化

第二部分是任務啓動優化,Flink 任務啓動的時候,一般會涉及到比較多的角色,還有多個實例。如下圖所示,它的啓動在客戶端包括,初始化 Client,構建 jobGraph,上傳 Flink lib、job jar,申請 AM。在 Job Master,AM 啓動後、初始化,構建 ExectutionGraph,申請、啓動 Container,Job Task 調度。在 Task  Manager 端, 容器申請到之後,啓動下載 jar 包資源,再去初始化 Task Manager  服務,然後收到 task 後纔會去做部署。我們發現,線上啓動一個任務的時候,基本上在分鐘級別,耗時比較長。如果有一些任務需要升級,比如說,改了一些簡單的邏輯,需要將原來的任務停掉,然後再去重新啓動一個新的任務,這種場景可能就會更慢。因此,我在任務啓動的時候做一些優化,儘可能縮短任務啓動的時間,業務的斷流時間也進一步縮短。

 

在 Flink 新任務啓動優化方面,我們發現 IO 交互會比較耗時。在客戶端的 IO 包括,Flink 引擎 lib 包上傳 HDFS,用戶上傳 jar 包上傳 HDFS。在 JobMaster 包括, Container 下載啓動資源,TaskManager conf 上傳 HDFS。在 TaskManager 包括, Container 下載啓動資源,Conf 文件下載。

因此,想盡量的減少這樣的一些 lO 的操作。針對 Flink 引擎 lib 包,設置 Public 權限,App 之間共享。對於用戶 jar 包,提供工具,提前預發佈到集羣機器。對於 Conf 文件,通過環境變量傳遞。針對 JobMaster 啓動 TM 頻繁文件判斷,增加 cache 緩存。

 

以上是針對一個新任務啓動場景,下面介紹任務升級的場景。以前是同步升級,比如說,任務 A 在運行着,然後我要把任務 A 停掉,再去啓動新的任務 B。如下圖所示,不可用時間包括停任務 A 和啓動新任務 B。是否可以不用等任務 A 完全停掉之後,再啓動任務 B。針對這個想法我們做了一個異步升級的策略。新任務提前啓動,初始化到 JobMaster 階段。舊任務停掉後,完成新任務後續啓動工作,這樣新舊任務無縫切換。通過內部提交平臺將該步驟串聯起來,目標是異步升級在 20s 以內完成。

03

Flink SQL 實踐與優化

第三部分會介紹一下我們在使用 Flink SQL 的一些實踐和優化。首先介紹一下 Flink   SQL 在快手的現狀。目前,我們內部 Flink SQL 的任務佔比在 30% 左右。Flink SQL 的任務個數是 360 多個。然後它的峯值處理的條目數還是比較高的,大約是 4 億每秒。在我們內部的一些重要活動的實時大屏的場景下,目前 Flink SQL 也作爲一條鏈路,參與了相關指標的計算。

 

接下來介紹一下我們在使用 Flink SQL 的時候遇到的一些問題,以及我們做的一些優化。首先,關於 Flink SQL 的傾斜問題,在 UnBounded Agg 場景下的傾斜問題,已經有比較全面的思路去解決,總結爲三點。

 

所以我們解決的第一個問題就是 Bounded Agg 的傾斜問題。如下圖所示,拿左邊的 SQL 作爲例子,group by 一個 user,假定一天的窗口,然後去 select 每一個用戶總的交易額。右邊的圖,假定有一些用戶的交易特別多,就會造成某一些 Window Agg 的數據量特別大。

 

解決思路分爲兩點。

 

 

我們解決的第二個問題是 Flink SQL 下的 UDF 函數複用的問題。如下圖所示,以左邊的 SQL 爲例,可以看到有兩個 UDF 的函數,這兩個函數在 SQL 裏面都重複出現了多次。

04

未來工作

第四部分介紹我們未來的一些規劃,分爲三塊。

今天的分享就到這裏,謝謝大家。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/EfdXZ-V4bKRWRIXUuXb9FA