Flink 1.10 同時還標志著對 Blink[1] 的整合宣告完成,隨著對 Hive 的生產級別集成及對 TPC-DS 的全面覆蓋,Flink 在增強流式 SQL 處理能力的同時也具備了成熟的批處理能力。本篇博客將對此次版本升級中的主要新特性及優化、值得注意的重要變化以及使用新版本的預期效果逐一進行介紹。
官網下載鏈接:https://flink.apache.org/downloads.html
新版本的二進制發布包和源碼包已經可以在最新的 Flink 官網下載頁面[2]找到。更多細節請參考完整的版本更新日志[3]以及最新的用戶文檔[4]。歡迎您下載試用此版本,并將您的反饋意見通過 Flink 郵件列表[5]或 JIRA[6] 與社區分享。
新特性及優化
內存管理及配置優化
Flink 目前的 TaskExecutor 內存模型存在著一些缺陷,導致優化資源利用率比較困難,例如:
- 流和批處理內存占用的配置模型不同;
- 流處理中的 RocksDB state backend 需要依賴用戶進行復雜的配置。
為了讓內存配置變的對于用戶更加清晰、直觀,Flink 1.10 對 TaskExecutor 的內存模型和配置邏輯進行了較大的改動 (FLIP-49 [7])。這些改動使得 Flink 能夠更好地適配所有部署環境(例如 Kubernetes, Yarn, Mesos),讓用戶能夠更加嚴格的控制其內存開銷。
Managed 內存擴展
Managed 內存的范圍有所擴展,還涵蓋了 RocksDB state backend 使用的內存。盡管批處理作業既可以使用堆內內存也可以使用堆外內存,使用 RocksDB state backend 的流處理作業卻只能利用堆外內存。因此為了讓用戶執行流和批處理作業時無需更改集群的配置,我們規定從現在起 managed 內存只能在堆外。
簡化 RocksDB 配置
此前,配置像 RocksDB 這樣的堆外 state backend 需要進行大量的手動調試,例如減小 JVM 堆空間、設置 Flink 使用堆外內存等。現在,Flink 的開箱配置即可支持這一切,且只需要簡單地改變 managed 內存的大小即可調整 RocksDB state backend 的內存預算。
另一個重要的優化是,Flink 現在可以限制 RocksDB 的 native 內存占用(FLINK-7289 [8]),以避免超過總的內存預算——這對于 Kubernetes 等容器化部署環境尤為重要。關于如何開啟、調試該特性,請參考 RocksDB 調試[9]。
注:FLIP-49 改變了集群的資源配置過程,因此從以前的 Flink 版本升級時可能需要對集群配置進行調整。詳細的變更日志及調試指南請參考文檔[10]。
統一的作業提交邏輯
在此之前,提交作業是由執行環境負責的,且與不同的部署目標(例如 Yarn, Kubernetes, Mesos)緊密相關。這導致用戶需要針對不同環境保留多套配置,增加了管理的成本。
在 Flink 1.10 中,作業提交邏輯被抽象到了通用的 Executor 接口(FLIP-73 [11])。新增加的 ExecutorCLI (FLIP-81 [12])引入了為任意執行目標[13]指定配置參數的統一方法。此外,隨著引入 JobClient(FLINK-74 [14])負責獲取 JobExecutionResult,獲取作業執行結果的邏輯也得以與作業提交解耦。
上述改變向用戶提供了統一的 Flink 入口,使得在 Apache Beam 或 Zeppelin notebooks 等下游框架中以編程方式使用 Flink 變的更加容易。對于需要在多種不同環境使用 Flink 的用戶而言,新的基于配置的執行過程同樣顯著降低了冗余代碼量以及維護開銷。
原生 Kubernetes 集成(Beta)
對于想要在容器化環境中嘗試 Flink 的用戶來說,想要在 Kubernetes 上部署和管理一個 Flink standalone 集群,首先需要對容器、算子及像 kubectl 這樣的環境工具有所了解。
在 Flink 1.10 中,我們推出了初步的支持 session 模式的主動 Kubernetes 集成(FLINK-9953 [15])。其中,“主動”指 Flink ResourceManager (K8sResMngr) 原生地與 Kubernetes 通信,像 Flink 在 Yarn 和 Mesos 上一樣按需申請 pod。用戶可以利用 namespace,在多租戶環境中以較少的資源開銷啟動 Flink。這需要用戶提前配置好 RBAC 角色和有足夠權限的服務賬號。
正如在統一的作業提交邏輯一節中提到的,Flink 1.10 將命令行參數映射到了統一的配置。因此,用戶可以參閱 Kubernetes 配置選項,在命令行中使用以下命令向 Kubernetes 提交 Flink 作業。
./bin/flink run -d -e kubernetes-session -Dkubernetes.cluster-id=<ClusterId> examples/streaming/WindowJoin.jar
如果你希望第一時間嘗試這一特性,歡迎參考相關文檔[16]、試用并與社區分享你的反饋意見:
Table API/SQL: 生產可用的 Hive 集成
Flink 1.9 推出了預覽版的 Hive 集成。該版本允許用戶使用 SQL DDL 將 Flink 特有的元數據持久化到 Hive Metastore、調用 Hive 中定義的 UDF 以及讀、寫 Hive 中的表。Flink 1.10 進一步開發和完善了這一特性,帶來了全面兼容 Hive 主要版本[17]的生產可用的 Hive 集成。
Batch SQL 原生分區支持
此前,Flink 只支持寫入未分區的 Hive 表。在 Flink 1.10 中,Flink SQL 擴展支持了 INSERT OVERWRITE 和 PARTITION 的語法(FLIP-63 [18]),允許用戶寫入 Hive 中的靜態和動態分區。
- 寫入靜態分區
INSERT { INTO | OVERWRITE } TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1 FROM from_statement;
- 寫入動態分區
INSERT { INTO | OVERWRITE } TABLE tablename1 select_statement1 FROM from_statement;
對分區表的全面支持,使得用戶在讀取數據時能夠受益于分區剪枝,減少了需要掃描的數據量,從而大幅提升了這些操作的性能。
其他優化
除了分區剪枝,Flink 1.10 的 Hive 集成還引入了許多數據讀取[19]方面的優化,例如:
- 投影下推:Flink 采用了投影下推技術,通過在掃描表時忽略不必要的域,最小化 Flink 和 Hive 表之間的數據傳輸量。這一優化在表的列數較多時尤為有效。
- LIMIT 下推:對于包含 LIMIT 語句的查詢,Flink 在所有可能的地方限制返回的數據條數,以降低通過網絡傳輸的數據量。
- 讀取數據時的 ORC 向量化: 為了提高讀取 ORC 文件的性能,對于 Hive 2.0.0 及以上版本以及非復合數據類型的列,Flink 現在默認使用原生的 ORC 向量化讀取器。
將可插拔模塊作為 Flink 內置對象(Beta)
Flink 1.10 在 Flink table 核心引入了通用的可插拔模塊機制,目前主要應用于系統內置函數(FLIP-68 [20])。通過模塊,用戶可以擴展 Flink 的系統對象,例如像使用 Flink 系統函數一樣使用 Hive 內置函數。新版本中包含一個預先實現好的 HiveModule,能夠支持多個 Hive 版本,當然用戶也可以選擇編寫自己的可插拔模塊 [21]。
其他 Table API/SQL 優化
SQL DDL 中的 watermark 和計算列
Flink 1.10 在 SQL DDL 中增加了針對流處理定義時間屬性及產生 watermark 的語法擴展(FLIP-66 [22])。這使得用戶可以在用 DDL 語句創建的表上進行基于時間的操作(例如窗口)以及定義 watermark 策略[23]。
CREATE TABLE table_name (
WATERMARK FOR columnName AS <watermark_strategy_expression>
) WITH (
...
)
其他 SQL DDL 擴展
Flink 現在嚴格區分臨時/持久、系統/目錄函數(FLIP-57 [24])。這不僅消除了函數引用中的歧義,還帶來了確定的函數解析順序(例如,當存在命名沖突時,比起目錄函數、持久函數 Flink 會優先使用系統函數、臨時函數)。
在 FLIP-57 的基礎上,我們擴展了 SQL DDL 的語法,支持創建目錄函數、臨時函數以及臨時系統函數(FLIP-79 [25]):
CREATE [TEMPORARY|TEMPORARY SYSTEM] FUNCTION
[IF NOT EXISTS] [catalog_name.][db_name.]function_name
AS identifier [LANGUAGE JAVA|SCALA]
關于目前完整的 Flink SQL DDL 支持,請參考最新的文檔[26]。
注:為了今后正確地處理和保證元對象(表、視圖、函數)上的行為一致性,Flink 廢棄了 Table API 中的部分對象申明方法,以使留下的方法更加接近標準的 SQL DDL(FLIP-64 [27])。
批處理完整的 TPC-DS 覆蓋
TPC-DS 是廣泛使用的業界標準決策支持 benchmark,用于衡量基于 SQL 的數據處理引擎性能。Flink 1.10 端到端地支持所有 TPC-DS 查詢(FLINK-11491 [28]),標志著 Flink SQL 引擎已經具備滿足現代數據倉庫及其他類似的處理需求的能力。
PyFlink: 支持原生用戶自定義函數(UDF)
作為 Flink 全面支持 Python 的第一步,在之前版本中我們發布了預覽版的 PyFlink。在新版本中,我們專注于讓用戶在 Table API/SQL 中注冊并使用自定義函數(UDF,另 UDTF / UDAF 規劃中)(FLIP-58 [29])。
如果你對這一特性的底層實現(基于 Apache Beam 的可移植框架 [30])感興趣,請參考 FLIP-58 的 Architecture 章節以及 FLIP-78 [31]。這些數據結構為支持 Pandas 以及今后將 PyFlink 引入到 DataStream API 奠定了基礎。
從 Flink 1.10 開始,用戶只要執行以下命令就可以輕松地通過 pip 安裝 PyFlink:
pip install apache-flink
更多 PyFlink 規劃中的優化,請參考 FLINK-14500[32],同時歡迎加入有關用戶需求的討論[33]。
重要變更
FLINK-10725[34]:Flink 現在可以使用 Java 11 編譯和運行。
FLINK-15495[35]:SQL 客戶端現在默認使用 Blink planner,向用戶提供最新的特性及優化。Table API 同樣計劃在下個版本中從舊的 planner 切換到 Blink planner,我們建議用戶現在就開始嘗試和熟悉 Blink planner。
FLINK-13025[36]:新的 Elasticsearch sink connector[37] 全面支持 Elasticsearch 7.x 版本。
FLINK-15115[38]:Kafka 0.8 和 0.9 的 connector 已被標記為廢棄并不再主動支持。如果你還在使用這些版本或有其他相關問題,請通過 @dev 郵件列表聯系我們。
FLINK-14516[39]:非基于信用的網絡流控制已被移除,同時移除的還有配置項“taskmanager.network.credit.model”。今后,Flink 將總是使用基于信用的網絡流控制。
FLINK-12122[40]:在 Flink 1.5.0 中,FLIP-6[41] 改變了 slot 在 TaskManager 之間的分布方式。要想使用此前的調度策略,既盡可能將負載分散到所有當前可用的 TaskManager,用戶可以在 flink-conf.yaml 中設置 “cluster.evenly-spread-out-slots: true”。
FLINK-11956[42]:
s3-hadoop 和 s3-presto 文件系統不再使用類重定位加載方式,而是使用插件方式加載,同時無縫集成所有認證提供者。我們強烈建議其他文件系統也只使用插件加載方式,并將陸續移除重定位加載方式。
Flink 1.9 推出了新的 Web UI,同時保留了原來的 Web UI 以備不時之需。截至目前,我們沒有收到關于新的 UI 存在問題的反饋,因此社區投票決定[43]在 Flink 1.10 中移除舊的 Web UI。
發行說明
準備升級到 Flink 1.10 的用戶,請參考發行說明[44]中的詳細變更及新特性列表。對于標注為 @Public 的 API,此版本與此前的 1.x 版本 API 兼容。