深度剖析阿里巴巴對 Apache Flink 的最佳化與改進
Apache Flink 概述
Apache Flink(以下簡稱 Flink)是誕生於歐洲的一個大資料研究專案,原名 StratoSphere。該專案是柏林工業大學的一個研究性專案,早期專注於批計算。2014 年,StratoSphere 專案中的核心成員孵化出 Flink,並在同年將 Flink 捐贈 Apache,後來 Flink 順利成為 Apache 的頂級大資料專案。同時 Flink 計算的主流方向被定位為流計算,即用流式計算來做所有大資料的計算工作,這就是 Flink 技術誕生的背景。
2014 年 Flink 作為主攻流計算的大資料引擎開始在開源大資料行業內嶄露頭角。區別於 Storm、Spark Streaming 以及其他流式計算引擎的是:它不僅是一個高吞吐、低延遲的計算引擎,同時還提供很多高階功能。比如它提供有狀態的計算,支援狀態管理,支援強一致性的資料語義以及支援 Event Time、WaterMark 對訊息亂序的處理等。
Flink 的受歡迎還離不開它身上的眾多標籤,其中包括效能優秀(尤其在流計算領域)、高可擴充套件性、支援容錯,是一種純記憶體式的一個計算引擎,做了記憶體管理方面的大量最佳化,另外也支援 eventime 的處理、支援超大狀態的 Job(在阿里巴巴中作業的 state 大小超過 TB 的是非常常見的)、支援 exactly-once 的處理。
阿里巴巴與 Flink
隨著人工智慧時代的降臨,資料量的爆發,在典型的大資料的業務場景下資料業務最通用的做法是:選用批處理的技術處理全量資料,採用流式計算處理實時增量資料。在絕大多數的業務場景之下,使用者的業務邏輯在批處理和流處理之中往往是相同的。但是,使用者用於批處理和流處理的兩套計算引擎是不同的。
因此,使用者通常需要寫兩套程式碼。毫無疑問,這帶來了一些額外的負擔和成本。阿里巴巴的商品資料處理就經常需要面對增量和全量兩套不同的業務流程問題,所以阿里巴巴就在想:能不能有一套統一的大資料引擎技術,使用者只需要根據自己的業務邏輯開發一套程式碼。這樣在各種不同的場景下,不管是全量資料還是增量資料,亦或者實時處理,一套方案即可全部支援,這就是阿里巴巴選擇 Flink 的背景和初衷。
基於 Flink 在阿里巴巴搭建的平臺於 2016 年正式上線,並從阿里巴巴的搜尋和推薦這兩大場景開始實現。目前阿里巴巴所有的業務,包括阿里巴巴所有子公司都採用了基於 Flink 搭建的實時計算平臺。同時 Flink 計算平臺執行在開源的 Hadoop 叢集之上。採用 Hadoop 的 YARN 做為資源管理排程,以 HDFS 作為資料儲存。因此,Flink 可以和開源大資料軟體 Hadoop 無縫對接。
目前,這套基於 Flink 搭建的實時計算平臺不僅服務於阿里巴巴集團內部,而且透過阿里雲的雲產品API向整個開發者生態提供基於 Flink 的雲產品支援。
彼時的 Flink 不管是規模還是穩定性尚未經歷實踐,成熟度有待商榷。阿里巴巴實時計算團隊決定在阿里內部建立一個 Flink 分支 Blink,並對 Flink 進行大量的修改和完善,讓其適應阿里巴巴這種超大規模的業務場景。在這個過程當中,該團隊不僅對 Flink 在效能和穩定性上做出了很多改進和最佳化,同時在核心架構和功能上也進行了大量創新和改進,並將逐漸推回給社群,例如:Flink 新的分散式架構,增量 Checkpoint 機制,基於 Credit-based 的網路流控機制和 Streaming SQL 等。接下來,我們主要從兩個層面深度剖析阿里巴巴對Flink究竟做了哪些最佳化?
取之開源,用之開源
SQL 層
為了能夠真正做到使用者根據自己的業務邏輯開發一套程式碼,能夠同時執行在多種不同的場景,Flink 首先需要給使用者提供一個統一的 API。在經過一番調研之後,阿里巴巴實時計算認為 SQL 是一個非常適合的選擇。在批處理領域,SQL 已經經歷了幾十年的考驗,是公認的經典。在流計算領域,近年來也不斷有流表二象性、流是表的 ChangeLog 等理論出現。在這些理論基礎之上,阿里巴巴提出了動態表的概念,使得流計算也可以像批處理一樣使用 SQL 來描述,並且邏輯等價。這樣一來,使用者就可以使用 SQL 來描述自己的業務邏輯,相同的查詢語句在執行時可以是一個批處理任務,也可以是一個高吞吐低延遲的流計算任務,甚至是先使用批處理技術進行歷史資料的計算,然後自動的轉成流計算任務處理最新的實時資料。在這種宣告式的 API 之下,引擎有了更多的選擇和最佳化空間。接下來,我們將介紹其中幾個比較重要的最佳化。
首先是對 SQL 層的技術架構進行升級和替換。調研過 Flink 或者使用過 Flink 的開發者應該知道,Flink 有兩套基礎的 API,一套是 DataStream,另一套是 DataSet。DataStream API 是針對流式處理的使用者提供,DataSet API 是針對批處理使用者提供,但是這兩套 API 的執行路徑是完全不一樣的,甚至需要生成不同的 Task 去執行。Flink 原生的 SQL 層在經過一系列最佳化之後,會根據使用者希望是批處理還是流處理的不同選擇,去呼叫 DataSet 或者是 DataStream API。這就會造成使用者在日常開發和最佳化中,經常要面臨兩套幾乎完全獨立的技術棧,很多事情可能需要重複的去做兩遍。這樣也會導致在一邊的技術棧上做的最佳化,另外一邊就享受不到。因此阿里巴巴在 SQL 層提出了全新的 Quyer Processor,它主要包括一個流和批可以儘量做到複用的最佳化層(Query Optimizer)以及基於相同介面的運算元層(Query Executor)。這樣一來, 80% 以上的工作可以做到兩邊複用,比如一些公共的最佳化規則,基礎資料結構等等。同時,流和批也會各自保留自己一些獨特的最佳化和運算元,以滿足不同的作業行為。
在 SQL 層的技術架構統一之後,阿里巴巴開始尋求一種更高效的基礎資料結構,以便讓 Blink 在 SQL 層的執行更加高效。在原生 Flink SQL中,都統一使用了一種叫 Row 的資料結構,它完全由 Java 的一些物件構成關聯式資料庫中的一行。假如現在的一行資料由一個整型,一個浮點型以及一個字串組成,那麼 Row 當中就會包含一個 Java 的 Integer、Double 和 String。眾所周知,這些 Java 的物件在堆內有不少的額外開銷,同時在訪問這些資料的過程中也會引入不必要的裝箱拆箱操作。基於這些問題,阿里巴巴提出了一種全新的資料結構 BinaryRow,它和原來的 Row 一樣也是表示一個關係資料中的一行,但與之不同的是,它完全使用二進位制資料來儲存這些資料。在上述例子中,三個不同型別的欄位統一由 Java 的 byte[] 來表示。這會帶來諸多好處:
- 首先在儲存空間上,去掉了很多無謂的額外消耗,使得物件的儲存更為緊湊;
- 其次在和網路或者狀態儲存打交道的時候,也可以省略掉很多不必要的序列化反序列化開銷;
- 最後在去掉各種不必要的裝箱拆箱操作之後,整個執行程式碼對 GC 也更加友好。
透過引入這樣一個高效的基礎資料結構,整個 SQL 層的執行效率得到了一倍以上的提升。
在運算元的實現層面,阿里巴巴引入了更廣範圍的程式碼生成技術。得益於技術架構和基礎資料結構的統一,很多程式碼生成技術得以達到更廣範圍的複用。同時由於 SQL 的強型別保證,使用者可以預先知道運算元需要處理的資料的型別,從而可以生成更有針對性更高效的執行程式碼。在原生 Flink SQL 中,只有類似 a > 2 或者 c + d 這樣的簡單表示式才會應用程式碼生成技術,在阿里巴巴最佳化之後,有一些運算元會進行整體的程式碼生成,比如排序、聚合等。這使得使用者可以更加靈活的去控制運算元的邏輯,也可以直接將最終執行程式碼嵌入到類當中,去掉了昂貴的函式呼叫開銷。一些應用程式碼生成技術的基礎資料結構和演算法,比如排序演算法,基於二進位制資料的 HashMap 等,也可以在流和批的運算元之間進行共享和複用,讓使用者真正享受到了技術和架構的統一帶來的好處。在針對批處理的某些場景進行資料結構或者演算法的最佳化之後,流計算的效能也能夠得到提升。接下來,我們聊聊阿里巴巴在 Runtime 層對 Flink 又大刀闊斧地進行了哪些改進。
Runtime 層
為了讓 Flink 在阿里巴巴的大規模生產環境中生根發芽,實時計算團隊如期遇到了各種挑戰,首當其衝的就是如何讓 Flink 與其他叢集管理系統進行整合。Flink 原生叢集管理模式尚未完善,也無法原生地使用其他其他相對成熟的叢集管理系統。基於此,一系列棘手的問題接連浮現:多租戶之間資源如何協調?如何動態的申請和釋放資源?如何指定不同資源型別?
為了解決這個問題,實時計算團隊經歷大量的調研與分析,最終選擇的方案是改造 Flink 資源排程系統,讓 Flink 可以原生地跑在 YARN 叢集之上;並且重構 Master 架構,讓一個 Job 對應一個 Master,從此 Master 不再是叢集瓶頸。以此為契機,阿里巴巴和社群聯手推出了全新的 Flip-6 架構,讓 Flink 資源管理變成可插拔的架構,為 Flink 的可持續發展打下了堅實的基礎。如今 Flink 可以無縫執行在 YARN、Mesos 和 K8S 之上,正是這個架構重要性的有力說明。
解決了 Flink 叢集大規模部署問題後,接下來的就是可靠和穩定性,為了保證 Flink 在生產環境中的高可用,阿里巴巴著重改善了 Flink 的 FailOver 機制。首先是 Master 的 FailOver,Flink 原生的 Master FailOver 會重啟所有的 Job,改善後 Master 任何 FailOver 都不會影響 Job 的正常執行;其次引入了 Region-based 的 Task FailOver,儘量減少任何 Task 的 FailOver 對使用者造成的影響。有了這些改進的保駕護航,阿里巴巴的大量業務方開始把實時計算遷移到 Flink 上執行。
Stateful Streaming 是 Flink 的最大亮點,基於 Chandy-Lamport 演算法的 Checkpoint 機制讓 Flink 具備 Exactly Once 一致性的計算能力,但在早期 Flink 版本中 Checkpoint 的效能在大規模資料量下存在一定瓶頸,阿里巴巴也在 Checkpoint 上進行了大量改進,比如:
- 增量 Checkpoint 機制:阿里巴巴生產環境中遇到大 Job 有幾十 TB State 是常事,做一次全量 CP 地動山搖,成本很高,因此阿里巴巴研發了增量 Checkpoint 機制,從此之後 CP 從暴風驟雨變成了細水長流;
- Checkpoint 小檔案合併:都是規模惹的禍,隨著整個叢集 Flink Job 越來越多,CP 檔案數也水漲船高,最後壓的 HDFS NameNode 不堪重負,阿里巴巴透過把若干 CP 小檔案合併成一個大檔案的組織方式,最終把 NameNode 的壓力減少了幾十倍。
雖然說所有的資料可以放在 State 中,但由於一些歷史的原因,使用者依然有一些資料需要存放在像 HBase 等一些外部 KV 儲存中,使用者在 Flink Job 需要訪問這些外部的資料,但是由於 Flink 一直都是單執行緒處理模型,導致訪問外部資料的延遲成為整個系統的瓶頸,顯然非同步訪問是解決這個問題的直接手段,但是讓使用者在 UDF 中寫多執行緒同時還要保證 ExactlyOnce 語義,卻並非易事。阿里巴巴在Flink中提出了 AsyncOperator,讓使用者在 Flink Job 中寫非同步呼叫和寫“Hello Word”一樣簡單 ,這個讓 Flink Job 的吞吐有了很大的飛躍。
Flink 在設計上是一套批流統一的計算引擎,在使用過快如閃電的流計算之後,批使用者也開始有興趣入住 Flink 小區。但批計算也帶來了新的挑戰,首先在任務排程方面,阿里巴巴引入了更加靈活的排程機制,能夠根據任務之間的依賴關係進行更加高效的排程;其次就是資料 Shuffle,Flink 原生的S huffle Service 和 TM 繫結,任務執行完之後要依舊保持 TM 無法釋放資源;還有就是原有的 Batch shuffle 沒有對檔案進行合併,所以基本無法在生產中使用。阿里巴巴開發了 Yarn Shuffle Service 功能的同時解決了以上兩個問題。在開發 Yarn Shuffle Service 的時候,阿里巴巴發現開發一套新的 Shuffle Service 非常不便,需要侵入 Flink 程式碼的很多地方,為了讓其他開發者方便的擴充套件不同 Shuffle,阿里巴巴同時改造了 Flink Shuffle 架構,讓 Flink 的 Shuffle 變成可插拔的架構。目前阿里巴巴的搜尋業務已經在使用 Flink Batch Job,並且已經開始服務於生產。
經過 3 年多打磨,Blink 已經在阿里巴巴開始茁壯生長,但是對 Runtime 的最佳化和改進是永無止境的,一大波改進和最佳化正在路上。
Flink 的未來方向
目前 Flink 已經是一個主流的流計算引擎,社群下一步很重要的工作是讓 Flink 在批計算上有所突破,在更多的場景下落地,成為一種主流的批計算引擎。然後進一步在流和批之間進行無縫的切換,流和批的界限越來越模糊。用 Flink,在一個計算中,既可以有流計算,又可以有批計算。
接下來阿里巴巴將致力於推動 Flink 在生態上得到更多語言的支援,不僅僅是 Java、Scala 語言,甚至是機器學習下用的 Python、Go 語言。
另一點不得不說 AI,因為現在很多大資料計算的需求和資料量都是在支援很火爆的 AI 場景,所以 Flink 在流批生態完善的基礎上,將繼續完善上層的 Machine Learning 演算法庫,同時 Flink 也會向更成熟的機器學習、深度學習去整合。比如可以做 Tensorflow On Flink, 讓大資料的 ETL 資料處理和機器學習的 Feature 計算和特徵計算,訓練的計算等進行整合,讓開發者能夠同時享受到多種生態給大家帶來的好處。
最後,從生態、社群的活躍來說,阿里巴巴目前在推進的一件事情是籌備 2018 年 12 月 20 日 - 21 日在國家會議中心舉辦的首屆 Flink Forward China 峰會(千人規模),參與者將有機會了解阿里巴巴、騰訊、華為、滴滴、美團、位元組跳動等公司為何將 Flink 作為首選的流處理引擎。
報名連結:https://dwz.cn/a4lHAVgW。
相關文章
- 取之開源,用之開源-深度剖析阿里巴巴對Flink的優化與改進阿里優化
- Apache Flink 進階(一):Runtime 核心機制剖析Apache
- Apache Flink 進階入門(二):Time 深度解析Apache
- Apache-Flink深度解析-TableAPIApacheAPI
- Apache-Flink深度解析-概述Apache
- Apache-Flink深度解析-SQL概覽ApacheSQL
- 阿里巴巴為什麼選擇Apache Flink?阿里Apache
- 深度剖析分散式事務之 AT 與 XA 對比分散式
- Flink CheckPoint狀態點恢復與savePoint機制對比剖析-Flink牛刀小試
- Apache Flink 在小米的穩定性最佳化和實踐Apache
- Apache Flink 進階(三):Checkpoint 原理解析與應用實踐Apache
- Apache-Flink深度解析-DataStream-Connectors之KafkaApacheASTKafka
- Flink Kafka Connector與Exactly Once剖析Kafka
- 使用Apache Flink和Apache Ignit進行資料流分析Apache
- Apache Flink 在鬥魚的應用與實踐Apache
- Apache Flink 在汽車之家的應用與實踐Apache
- SQL 層功能改進 - lookupJoin 的最佳化SQL
- Apache 與 Nginx 效能對比:Web 伺服器最佳化技術ApacheNginxWeb伺服器
- Apache安裝與最佳化教程。Apache
- Eta中的Apache Flink示例Apache
- apache flink 簡介Apache
- 對通用骨架提取方法的改進
- Apache Ignite剖析Apache
- flink 類載入剖析
- Android對話方塊Dialog深度剖析Android
- Android 對話方塊 Dialog 深度剖析Android
- iOS:對array,dictionary,set的分析,對dictionary的改進iOS
- Apache 流框架 Flink,Spark Streaming,Storm對比分析(2)Apache框架SparkORM
- Apache 流框架 Flink,Spark Streaming,Storm對比分析(1)Apache框架SparkORM
- Apache 流框架 Flink,Spark Streaming,Storm對比分析(一)Apache框架SparkORM
- Apache 流框架 Flink,Spark Streaming,Storm對比分析(二)Apache框架SparkORM
- 自我反省與改進
- mac安裝apache flinkMacApache
- Apache Flink核心技術Apache
- [Flink] Flink 版本特性的演進
- Apache Spark原始碼剖析ApacheSpark原始碼
- Apache Flink 進階(五):資料型別和序列化Apache資料型別
- Log4j2 Zero Day 漏洞 Apache Flink 應對指南Apache