精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

一條 FlinkSQL 從提交到運行結束到底經(jīng)歷了哪些奇妙的故事?

大數(shù)據(jù)
本文我們將逐一揭開Flink SQL神秘的面紗,深入解析其經(jīng)歷的每一個關鍵階段:SQL提交與解析、語法驗證、邏輯計劃生成、邏輯計劃優(yōu)化、物理計劃轉換、JobGraph構建、作業(yè)提交與調度、分布式執(zhí)行與狀態(tài)管理,以及最終的作業(yè)終結。

Apache Flink,作為業(yè)界領先的流處理框架,以其卓越的性能、精確一次(Exactly-Once)的狀態(tài)管理和強大的事件時間處理能力,贏得了廣泛的贊譽。而Flink SQL,作為Flink提供的高級API,更是將復雜的流處理邏輯封裝在簡潔的SQL語句中,極大地降低了實時開發(fā)的門檻,讓數(shù)據(jù)分析師和工程師都能輕松構建強大的實時應用。

我們常常驚嘆于Flink SQL的簡潔與強大,一條簡單的INSERT INTO ... SELECT ... FROM ...語句,就能啟動一個復雜的、分布式的、高可用的流處理作業(yè)。然而,這行代碼背后究竟隱藏著怎樣的技術奇觀?它如何從一個靜態(tài)的文本字符串,演變成一個在集群中奔騰不息的數(shù)據(jù)洪流?

這篇文章將帶你踏上一場深度探索之旅,我們將以“上帝視角”全程跟蹤一條Flink SQL從被敲下的那一刻起,到最終在集群中穩(wěn)定運行、處理數(shù)據(jù)、直至結束的完整生命周期。我們將逐一揭開其神秘的面紗,深入解析其經(jīng)歷的每一個關鍵階段:SQL提交與解析、語法驗證、邏輯計劃生成、邏輯計劃優(yōu)化、物理計劃轉換、JobGraph構建、作業(yè)提交與調度、分布式執(zhí)行與狀態(tài)管理,以及最終的作業(yè)終結。

這不僅是一次技術原理的梳理,更是一次對現(xiàn)代分布式計算系統(tǒng)設計哲學的洞察。準備好了嗎?讓我們一同潛入Flink SQL的冰山之下,探索那個宏偉而精密的內在世界。

第一章:旅程的起點 - SQL提交與客戶端網(wǎng)關

一切故事都始于一個意圖。用戶,無論是通過命令行工具、IDE插件還是應用程序,編寫了一條SQL語句,意圖從某個數(shù)據(jù)源(如Kafka)讀取數(shù)據(jù),經(jīng)過一系列轉換,最終將結果寫入某個目標(如MySQL、Elasticsearch或另一個Kafka主題)。

1. 多樣的提交渠道

Flink SQL提供了多種與用戶交互的入口,以適應不同的使用場景:

  • SQL Client:這是Flink官方提供的命令行工具,非常適合進行交互式查詢和快速原型驗證。用戶啟動SQL Client后,會進入一個類似MySQL的命令行界面。在這里,用戶可以逐條輸入SQL語句,按下回車鍵,客戶端便會將這條SQL語句封裝成一個請求,發(fā)送給其背后連接的Flink集群。SQL Client本身不執(zhí)行任何計算,它只是一個輕量級的“信使”。
  • SQL Gateway:對于生產環(huán)境,一個長期運行、可被多用戶/多應用并發(fā)訪問的服務更為合適。SQL Gateway正是為此而生。它是一個獨立的守護進程,提供了RESTful API接口。任何能夠發(fā)送HTTP請求的客戶端(如Web應用、Java/Python程序)都可以通過調用這些API來提交SQL查詢、獲取結果、管理會話等。SQL Gateway負責管理用戶的會話狀態(tài)、維護Catalog(元數(shù)據(jù))信息,并將SQL請求安全地轉發(fā)給Flink集群。它解耦了客戶端與計算集群,提供了更好的隔離性和可管理性。
  • Table API(編程式):對于需要將Flink SQL深度集成到Java/Scala應用程序中的場景,F(xiàn)link提供了Table API。開發(fā)者可以在代碼中直接嵌入SQL字符串,并通過TableEnvironment對象來執(zhí)行它。例如:
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
StreamTableEnvironment tableEnv = StreamTableEnvironment.create(env);

// 在代碼中定義和執(zhí)行SQL
tableEnv.executeSql("CREATE TABLE KafkaSource (...) WITH (...)");
tableEnv.executeSql("CREATE TABLE MySqlSink (...) WITH (...)");

// 提交SQL查詢,這會觸發(fā)后續(xù)所有流程
TableResult result = tableEnv.executeSql(
    "INSERT INTO MySqlSink " +
    "SELECT userId, COUNT(*) AS cnt FROM KafkaSource WHERE action = 'click' GROUP BY userId"
);

這種方式賦予了開發(fā)者最大的靈活性,可以在SQL和更底層的DataStream API之間無縫切換。

2. 進入“黑盒”:TableEnvironment

無論通過哪種渠道提交,SQL語句最終都會抵達一個核心組件——TableEnvironment。可以將其理解為Flink SQL世界的“中央處理器”或“編譯器前端”。它負責維護整個SQL執(zhí)行上下文,包括:

  • Catalog:元數(shù)據(jù)的注冊中心,記錄了所有的表、視圖、函數(shù)等信息及其對應的物理連接器、數(shù)據(jù)格式、Schema等。
  • 當前數(shù)據(jù)庫/命名空間:類似于傳統(tǒng)數(shù)據(jù)庫的USE database。
  • 配置參數(shù):影響SQL執(zhí)行行為的各種參數(shù),如時區(qū)、空閑狀態(tài)保留時間等。

當tableEnv.executeSql(sql)被調用時,這條SQL字符串就正式踏上了它在Flink內部的奇幻漂流。TableEnvironment接收到這個字符串后,第一站便是“語言學院”——解析與驗證。

第二章:解構語言 - SQL解析與驗證

計算機無法直接理解人類自然語言或SQL這樣的聲明式語言。它需要將這段文本翻譯成一種結構化的、機器可讀的格式。這個過程分為兩步:詞法/語法分析和語義分析。

1. 詞法與語法分析:從字符串到語法樹

這個過程的核心是Apache Calcite,一個強大的、可擴展的動態(tài)數(shù)據(jù)管理框架。Flink SQL深度依賴Calcite來完成SQL的解析、優(yōu)化和執(zhí)行計劃的生成。

  • 詞法分析:Calcite的解析器首先會掃描SQL字符串,將其拆分成一個個有意義的最小單元,稱為“詞法單元”。例如,SELECT userId FROM events會被拆分為SELECT(關鍵字)、userId(標識符)、FROM(關鍵字)、events(標識符)。
  • 語法分析:接下來,解析器會根據(jù)預定義的SQL語法規(guī)則(通常以BNF范式定義),檢查這些詞法單元的組合是否構成一個合法的SQL語句。這個過程就像我們檢查一個句子的主謂賓是否齊全、語序是否正確。

如果語法正確,解析器會生成一個抽象語法樹。AST是一種樹形數(shù)據(jù)結構,它精確地表達了SQL語句的語法結構。每個節(jié)點代表一個語法成分,如一個查詢塊、一個表名、一個表達式等。

例如,對于SQL SELECT a, b FROM t WHERE c > 10,其AST可能簡化為:

SelectStmt
         /      \
    ProjectList   WhereClause
      /    \          |
    a      b      BinaryExpr(>)
                   /    \
                  c      10

AST是純語法層面的,它只關心“結構”,不關心“含義”。

2. 語義分析:賦予語法以意義

一個語法正確的SQL語句可能仍然是毫無意義或錯誤的。例如,SELECT non_existent_column FROM my_table。語義分析階段的目的就是檢查SQL的“含義”是否正確,確保它在當前TableEnvironment的上下文中是可執(zhí)行的。

TableEnvironment會遍歷AST,并執(zhí)行一系列檢查:

  • 對象存在性檢查:查詢中引用的表、視圖、函數(shù)是否在Catalog中注冊?
  • 字段/列存在性檢查:訪問的列是否存在于對應的表中?
  • 類型兼容性檢查:表達式中的操作數(shù)類型是否匹配?例如,WHERE age > 'twenty',如果age是整數(shù)類型,這里就會報類型不匹配的錯誤。函數(shù)調用的參數(shù)類型和數(shù)量是否正確?
  • 聚合與GROUP BY檢查:SELECT子句中的非聚合列是否都出現(xiàn)在GROUP BY子句中?
  • 權限檢查(在更復雜的部署中):用戶是否有權限訪問指定的表或執(zhí)行特定操作?

如果語義分析發(fā)現(xiàn)任何錯誤,它會拋出一個ValidationException,并將詳細的錯誤信息返回給用戶,整個流程就此終止。

如果所有檢查都通過,SQL語句就被認為是“有效”的。此時,AST雖然仍然是語法樹,但其中的每個節(jié)點都已經(jīng)被賦予了豐富的語義信息(如數(shù)據(jù)類型、表的Schema等)。這個經(jīng)過驗證的AST,是通往下一階段——邏輯計劃生成的基石。

第三章:構建藍圖 - 從SQL到邏輯計劃

現(xiàn)在我們有了一個經(jīng)過驗證的、語義清晰的AST。下一步是將其轉換為一個更能體現(xiàn)關系代數(shù)思想的邏輯計劃。邏輯計劃是關系數(shù)據(jù)庫理論的核心,它描述了“需要做什么”,而不關心“具體怎么做”。

1. RelNode樹:Calcite的邏輯表示

在Calcite的世界里,邏輯計劃由一棵RelNode樹來表示。每個RelNode代表一個關系操作,如掃描、過濾、投影、連接、聚合等。RelNode樹從根到葉描述了數(shù)據(jù)的計算流程。

轉換過程大致如下:TableEnvironment會調用Calcite的SqlToRelConverter,它會遞歸地遍歷驗證后的AST,并將每個語法節(jié)點映射為對應的RelNode。

讓我們通過一個具體的例子來理解這個過程:

INSERT INTO sink_table
SELECT
  user_id,
  COUNT(*) AS purchase_cnt
FROM source_table
WHERE event_type = 'purchase'
GROUP BY user_id
  • FROM source_table:AST中的表引用節(jié)點會被轉換為一個LogicalTableScan節(jié)點。這個節(jié)點代表了從source_table這個邏輯表中讀取數(shù)據(jù)的操作。它是整個RelNode樹的葉子節(jié)點。
  • WHERE event_type = 'purchase':這個過濾條件會被轉換為一個LogicalFilter節(jié)點。它的輸入是上一步生成的LogicalTableScan節(jié)點,表示數(shù)據(jù)流先經(jīng)過表掃描,再進行過濾。
  • GROUP BY user_id, COUNT(*):聚合操作會被轉換為一個LogicalAggregate節(jié)點。它的輸入是LogicalFilter節(jié)點。這個節(jié)點內部包含了分組鍵(user_id)和聚合函數(shù)(COUNT(*))。
  • SELECT user_id, COUNT(*) AS purchase_cnt:投影操作(選擇最終的輸出列并可能重命名)會被轉換為一個LogicalProject節(jié)點。它的輸入是LogicalAggregate節(jié)點。它定義了從上游節(jié)點的輸出中提取哪些列,以及如何進行計算和重命名。
  • INSERT INTO sink_table:這個寫入操作在邏輯計劃階段通常被特殊處理。它不是一個RelNode,而是作為整個查詢的“匯”信息被記錄下來。

最終,我們得到一棵未經(jīng)優(yōu)化的初始邏輯計劃樹(RelNode樹),其結構如下:

LogicalProject(user_id, COUNT(*) AS purchase_cnt)
  |
  +-- LogicalAggregate(group by: [user_id], aggregates: [COUNT(*)])
       |
       +-- LogicalFilter(condition: [event_type = 'purchase'])
            |
            +-- LogicalTableScan(table: [source_table])

這棵樹精確地描述了數(shù)據(jù)處理的邏輯步驟,但它可能不是最高效的。比如,過濾操作應該在聚合之前執(zhí)行,但目前的樹結構已經(jīng)體現(xiàn)了這一點。然而,還有更多潛在的優(yōu)化空間,這正是下一階段要解決的問題。

第四章:精煉與優(yōu)化 - 邏輯計劃優(yōu)化

初始的邏輯計劃雖然功能正確,但往往執(zhí)行效率低下。它就像一份建筑師畫的初稿,功能齊全但細節(jié)粗糙。優(yōu)化器的任務就是對其進行精雕細琢,生成一份更高效的執(zhí)行藍圖。

Flink SQL的優(yōu)化器同樣是基于Calcite構建的,主要采用兩種優(yōu)化策略:基于規(guī)則的優(yōu)化和基于成本的優(yōu)化。

1. 基于規(guī)則的優(yōu)化

RBO是一套啟發(fā)式的“經(jīng)驗法則”,優(yōu)化器會遍歷RelNode樹,并嘗試應用這些規(guī)則來重寫計劃樹。這些規(guī)則通常是“公理”,即應用后不會改變最終結果,但能提升性能。

一些經(jīng)典的RBO規(guī)則包括:

(1) 謂詞下推:這是最重要、最有效的優(yōu)化規(guī)則之一。其核心思想是將過濾條件盡可能地向數(shù)據(jù)源方向推送。在RelNode樹中,這意味著LogicalFilter節(jié)點會被移動到LogicalJoin節(jié)點的下方。

為什么? 因為越早過濾數(shù)據(jù),后續(xù)操作需要處理的數(shù)據(jù)量就越小。這能顯著減少網(wǎng)絡傳輸、內存占用和CPU計算。

例子:在JOIN操作中,如果有一個過濾條件只涉及其中一張表,那么應該先對這張表進行過濾,再執(zhí)行JOIN。

-- 優(yōu)化前
SELECT * FROM A JOIN B ON A.id = B.id WHERE A.age > 20

-- 優(yōu)化后(謂詞下推)
SELECT * FROM (SELECT * FROM A WHERE age > 20) A_filtered JOIN B ON A_filtered.id = B.id

(2) 投影剪枝:移除所有在最終結果中不被使用的列。

為什么? 減少每條記錄的數(shù)據(jù)大小,從而降低內存消耗和網(wǎng)絡I/O。

例子:如果source_table有100列,但查詢最終只用到user_id和event_type兩列,那么在邏輯計劃中,LogicalTableScan節(jié)點之后應該緊跟著一個LogicalProject節(jié)點,只保留這兩列,后續(xù)的所有操作都基于這個“瘦身”后的數(shù)據(jù)流進行。

(3) 常量折疊:在編譯期間預先計算出結果為常量的表達式。

例子:WHERE price * 1.1 > 100 AND 1 + 2 = 3 會被優(yōu)化為 WHERE price * 1.1 > 100 AND TRUE,進一步簡化為 WHERE price * 1.1 > 100。

(4) 合并操作:將連續(xù)的、可以合并的操作合并成一個。

例子:兩個連續(xù)的LogicalFilter節(jié)點可以被合并成一個,其條件是AND關系。一個LogicalProject節(jié)點如果只是簡單地重命名列,可能會和另一個LogicalProject合并。

優(yōu)化器會反復掃描RelNode樹,應用所有適用的規(guī)則,直到?jīng)]有規(guī)則可以再應用為止,此時得到的是一個經(jīng)過RBO優(yōu)化的邏輯計劃。

2. 基于成本的優(yōu)化

RBO雖然有效,但它不考慮數(shù)據(jù)的實際特征。例如,對于JOIN操作,RBO不知道應該用哪張表作為驅動表(廣播哈希連接中的小表)更高效。CBO則彌補了這一不足。

CBO的核心思想是:為同一個邏輯操作生成多種不同的物理實現(xiàn)方式,并根據(jù)數(shù)據(jù)統(tǒng)計信息估算每種方式的執(zhí)行成本,選擇成本最低的那個。

(1) 統(tǒng)計信息收集:CBO的決策依賴于準確的統(tǒng)計信息。Flink可以通過ANALYZE TABLE語句手動收集表的統(tǒng)計信息,或者某些Source連接器(如JDBC)也能提供元數(shù)據(jù)統(tǒng)計。這些信息包括:

  • 表的行數(shù)(表大小)
  • 列的基數(shù)(NDV,Number of Distinct Values,唯一值數(shù)量)
  • 列的數(shù)據(jù)分布(直方圖)
  • 列是否為空(NULL)等

(2) 成本模型:Flink內置了一個成本模型,它會根據(jù)RelNode的類型和輸入數(shù)據(jù)的統(tǒng)計信息,來估算其執(zhí)行成本。成本通常由I/O成本(讀寫數(shù)據(jù)量)和CPU成本(計算復雜度)加權得出。

(3) 計劃枚舉與選擇:對于像JOIN這樣的關鍵操作,CBO會考慮多種物理實現(xiàn)策略:CBO會利用統(tǒng)計信息估算每種策略的成本,并選擇成本最低的那個。

  • Broadcast Hash Join:如果一張表很小,可以將其廣播到所有下游任務,在內存中構建哈希表,然后與另一張大表進行流式關聯(lián)。成本取決于小表的大小。
  • Shuffle Hash Join:如果兩張表都很大,則需要對JOIN key進行shuffle,將相同key的數(shù)據(jù)發(fā)送到同一個任務,然后在任務內存中構建哈希表進行關聯(lián)。成本取決于網(wǎng)絡shuffle的數(shù)據(jù)量和兩表的大小。
  • Nested-Loop Join:通常效率最低,但在特定情況下(如右表非常小且沒有索引)可能被考慮。

經(jīng)過RBO和CBO的雙重洗禮,我們最終得到了一棵高度優(yōu)化的邏輯計劃樹。這棵樹在邏輯上是最優(yōu)的,但它仍然是抽象的,無法直接在Flink集群上執(zhí)行。下一步,就是將其翻譯成Flink能懂的“物理語言”。

第五章:連接現(xiàn)實 - 從邏輯計劃到物理計劃

如果說邏輯計劃是“做什么”的藍圖,那么物理計劃就是“怎么做”的施工圖。它需要將抽象的關系操作,具體化為Flink運行時能夠理解和執(zhí)行的算子。

1. FlinkPhysicalRel:Flink的物理計劃節(jié)點

Flink定義了一套自己的物理計劃節(jié)點,它們都繼承自Calcite的PhysicalRel接口,通常以Exec結尾,如StreamExecCalc、StreamExecAggregate、StreamExecJoin等。這些節(jié)點直接映射了Flink DataStream API中的算子。

轉換過程由FlinkRelOptPlanner的transform方法驅動,它會遍歷優(yōu)化后的邏輯RelNode樹,并將每個節(jié)點替換為對應的Flink物理節(jié)點。

  • LogicalProject 和 LogicalFilter 通常會被合并成一個 StreamExecCalc。Calc是計算(Calculate)的縮稱,它可以同時實現(xiàn)投影和過濾功能,效率更高。
  • LogicalAggregate 會被轉換為 StreamExecGroupAggregate。在流處理場景下,為了處理無限數(shù)據(jù)流和實現(xiàn)增量計算,F(xiàn)link的聚合算子非常復雜,需要依賴狀態(tài)和窗口。
  • LogicalJoin 會被轉換為 StreamExecJoin。根據(jù)JOIN的類型(Regular Join, Interval Join, Temporal Table Join)和窗口的設置,會生成不同的物理Join算子。
  • LogicalTableScan 會被轉換為 StreamExecTableSourceScan,它直接關聯(lián)到用戶在DDL中定義的Connector和Format。

2. 流處理特有的物理轉換

在流處理模式下,這個轉換過程需要特別處理一些關鍵概念:

窗口:SQL中的GROUP BY TUMBLE/HOP/SESSION(...)子句,在邏輯計劃中可能被表示為特殊的LogicalWindow節(jié)點。在轉換為物理計劃時,它們會被具體化為窗口算子,如StreamExecGlobalWindowAggregate,并負責分配窗口、觸發(fā)計算等。

兩階段聚合:為了優(yōu)化分布式聚合的性能,F(xiàn)link的物理計劃器會智能地引入一個兩階段聚合的優(yōu)化。

問題:如果所有數(shù)據(jù)都通過網(wǎng)絡shuffle到一個聚合節(jié)點進行計算,該節(jié)點會成為瓶頸,且容易發(fā)生數(shù)據(jù)傾斜。

解決方案:在本地聚合(Local Aggregation)之前,先進行一次預聚合(Pre-aggregation)。

  • 第一階段(本地預聚合):數(shù)據(jù)在進入網(wǎng)絡shuffle之前,先在各自的算子實例中進行一次部分聚合。例如,COUNT會累加本地的計數(shù),SUM會累加本地的和。
  • 第二階段(全局聚合):將預聚合后的結果進行shuffle,然后在全局聚合算子中進行最終的匯總。在物理計劃中,一個LogicalAggregate節(jié)點可能會被展開為LocalAggregate + GlobalAggregate兩個物理節(jié)點。這大大減少了網(wǎng)絡shuffle的數(shù)據(jù)量。

經(jīng)過這一系列轉換,我們最終得到了一棵Flink物理計劃樹(FlinkPhysicalRel樹)。這棵樹上的每一個節(jié)點都對應著一個或多個具體的Flink運行時算子,它們之間的連接關系也明確了數(shù)據(jù)是如何流動的。現(xiàn)在,我們離一個可執(zhí)行的Flink作業(yè)只有一步之遙了。

第六章:鑄就作業(yè) - 從物理計劃到JobGraph

物理計劃雖然已經(jīng)很具體,但它仍然是一個“計劃”。Flink集群需要一個更底層、更面向資源調度的數(shù)據(jù)結構來描述一個作業(yè),這就是JobGraph。

1. JobGraph:Flink作業(yè)的執(zhí)行藍圖

JobGraph是Flink作業(yè)被提交給JobManager的最終形式。它是一個有向無環(huán)圖(DAG),由以下核心元素構成:

  • JobVertex:代表一個可以并行執(zhí)行的“算子鏈”。一個JobVertex是JobGraph的基本調度單元。
  • JobEdge:代表兩個JobVertex之間的數(shù)據(jù)連接,定義了數(shù)據(jù)的分發(fā)模式(如POINTWISE點對點,ALL_TO_ALL全連接,后者對應于keyBy或rebalance)和交換數(shù)據(jù)的類型(如PIPELINED流式交換,BLOCKING批處理交換)。
  • IntermediateDataSet:代表JobVertex的輸出,是JobEdge的數(shù)據(jù)源。

2. 算子鏈:性能優(yōu)化的關鍵

從物理計劃樹到JobGraph的轉換過程中,一個至關重要的優(yōu)化是算子鏈。

概念:將多個物理算子合并到一個JobVertex中,讓它們在同一個線程(Task)中串行執(zhí)行。

為什么? 為了減少線程間切換和網(wǎng)絡通信的開銷。如果兩個算子之間是Forward分發(fā)(即上下游并行度一樣,數(shù)據(jù)一對一發(fā)送),那么將它們鏈接在一起,數(shù)據(jù)就可以直接在內存中傳遞,無需序列化/反序列化和網(wǎng)絡傳輸。

鏈接條件:并非所有算子都能被鏈接。主要的限制包括:

  • 算子之間的數(shù)據(jù)分發(fā)模式不能是ALL_TO_ALL(即不能有keyBy、broadcast等改變分區(qū)的操作)。
  • 上下游算子的并行度必須相同。
  • 不能打破用戶對shuffle的顯式控制。

例如,一個典型的流處理作業(yè)鏈可能是:Source -> Filter -> Map -> Keyed Aggregation -> Sink。其中,Source -> Filter -> Map可以被鏈接成一個JobVertex,因為它們之間都是Forward分發(fā)。而Keyed Aggregation會引入keyBy(ALL_TO_ALL分發(fā)),所以它必須成為一個獨立的JobVertex。Sink通常也是獨立的。

3. 構建過程

PipelineExecutor會遍歷物理計劃樹,執(zhí)行以下操作:

  • 創(chuàng)建JobVertex:為物理計劃樹的每個節(jié)點(或一組可鏈接的節(jié)點)創(chuàng)建一個JobVertex。
  • 設置并行度:為每個JobVertex設置并行度。這個并行度可以來自表配置、執(zhí)行環(huán)境配置,也可以是算子特定的配置。
  • 建立JobEdge:根據(jù)物理節(jié)點之間的數(shù)據(jù)流和分區(qū)策略,創(chuàng)建JobEdge來連接JobVertex。
  • 序列化算子:將每個物理算子(StreamOperator)及其配置(StreamConfig)序列化,并存儲在對應的JobVertex中。這些信息在后續(xù)被TaskManager加載以實例化實際的算子。

最終,一個完整的、可序列化的JobGraph對象被構建出來。它就像一個包含了所有施工指令、物料清單和設計圖紙的壓縮包,準備被發(fā)送到Flink集群的“總指揮部”——JobManager。

第七章:集群的心跳 - JobGraph提交與調度

現(xiàn)在,JobGraph已經(jīng)整裝待發(fā)。它需要被提交到Flink集群,并由集群的調度系統(tǒng)來驅動其執(zhí)行。

1. 提交到Dispatcher

客戶端(無論是SQL Client、SQL Gateway還是應用程序)通過REST API將JobGraph提交給Flink集群的Dispatcher組件。

Dispatcher:是集群的“前臺接待員”。它不直接執(zhí)行作業(yè),而是負責接收作業(yè)提交請求,為每個作業(yè)啟動一個專屬的JobMaster(也稱為Dispatcher的JobGraph的leader),然后將作業(yè)的管理權移交給這個JobMaster。

2. JobMaster:作業(yè)的大腦

一旦JobMaster被啟動,它就成為這個特定作業(yè)的“總指揮”。它的生命周期與作業(yè)綁定,負責作業(yè)的整個執(zhí)行過程。

(1) 接收JobGraph:JobMaster從Dispatcher那里獲取JobGraph。

(2) 構建ExecutionGraph:這是JobGraph的“并行化”和“可執(zhí)行化”版本。ExecutionGraph是JobMaster進行調度、狀態(tài)管理和故障恢復的核心數(shù)據(jù)結構。

  • JobGraph中的一個JobVertex(代表一個算子鏈)會被展開成一個ExecutionJobVertex。
  • ExecutionJobVertex會根據(jù)其并行度,創(chuàng)建多個ExecutionVertex。每個ExecutionVertex代表了該算子鏈的一個并行子任務。
  • ExecutionVertex之間通過ExecutionEdge連接,形成了ExecutionGraph。
  • 每個ExecutionVertex的當前執(zhí)行狀態(tài)被封裝在Execution對象中。Execution記錄了該子任務的嘗試次數(shù)、所在TaskManager、當前狀態(tài)(如SCHEDULED、DEPLOYING、RUNNING、FINISHED、FAILED)等。

(3) 資源申請與調度:

  • JobMaster會查看ExecutionGraph,確定需要部署多少個ExecutionVertex(即多少個并行子任務)。
  • 它會向集群的ResourceManager請求所需的TaskSlot(任務槽)。TaskSlot是TaskManager中資源分配的基本單位,一個TaskSlot代表一個固定的資源集合(如一定大小的內存、CPU核心)。
  • ResourceManager會根據(jù)集群的資源狀況,在某個或某些TaskManager上分配空閑的TaskSlot,并將TaskSlot的歸屬信息返回給JobMaster。

(4) 任務部署:

一旦JobMaster獲得了TaskSlot,它就會將ExecutionVertex(即子任務)部署到對應的TaskManager的TaskSlot中。

部署過程包括:將序列化的算子信息(StreamOperator和StreamConfig)、任務配置、以及整個ExecutionGraph的相關信息通過網(wǎng)絡發(fā)送給目標TaskManager。

3. TaskManager:作業(yè)的工人

TaskManager是Flink集群的“工作節(jié)點”,是真正執(zhí)行計算的地方。

  • 接收任務:TaskManager接收到JobMaster的部署請求后,會在指定的TaskSlot中啟動一個Task線程。
  • 實例化算子:Task線程會反序列化StreamOperator和StreamConfig,根據(jù)這些信息實例化用戶代碼中定義的算子(如FilterFunction、MapFunction)以及Flink的內置算子(如窗口算子、狀態(tài)后端)。
  • 建立網(wǎng)絡連接:Task會與上游和下游的Task建立網(wǎng)絡連接(基于Netty),為數(shù)據(jù)交換做好準備。
  • 啟動任務:一切準備就緒后,Task開始執(zhí)行。它會調用算子的open()方法(用于初始化,如打開狀態(tài)后端),然后進入主循環(huán),不斷地從上游接收數(shù)據(jù),調用算子的處理邏輯,并將結果發(fā)送到下游。

至此,一條SQL語句終于從一個靜態(tài)的文本,徹底“活”了過來,變成了一個在分布式集群中協(xié)同工作、高速處理數(shù)據(jù)的物理實體。

第八章:數(shù)據(jù)流動與作業(yè)終結

作業(yè)啟動后,便進入了漫長的運行階段。這個階段是Flink流處理能力的核心體現(xiàn)。

1. 數(shù)據(jù)的流動與處理

  • 數(shù)據(jù)記錄:數(shù)據(jù)以StreamRecord的形式在算子之間流動。每個StreamRecord包含了實際的數(shù)據(jù)值以及一個時間戳(可以是事件時間或處理時間)。
  • 算子處理:每個算子(StreamOperator)都實現(xiàn)了processElement()方法。當一條數(shù)據(jù)到達時,這個方法被調用。算子可以執(zhí)行任意的用戶邏輯,如過濾、轉換、聚合等。
  • 狀態(tài)管理:對于有狀態(tài)的計算(如聚合、窗口),算子會使用狀態(tài)后端來存儲和訪問狀態(tài)。Flink提供了多種狀態(tài)后端(如HashMapStateBackend、RocksDBStateBackend),可以將狀態(tài)存儲在JVM堆內存或本地磁盤上。
  • 容錯機制:檢查點:為了保證Exactly-Once語義,JobMaster會周期性地向所有Source算子注入一個特殊的檢查點屏障。這個屏障會像數(shù)據(jù)一樣,以相同的速度向下游流動。當一個算子收到所有上游輸入流的屏障后,它會將自己的當前狀態(tài)快照持久化到外部存儲(如HDFS、S3),然后將屏障繼續(xù)向下游廣播。當Sink算子也收到屏障并完成快照后,整個作業(yè)的一個全局一致性快照就完成了。如果作業(yè)發(fā)生故障,JobMaster可以從最近一次成功的檢查點恢復所有算子的狀態(tài),并讓數(shù)據(jù)源從記錄的偏移量重新開始消費,從而保證數(shù)據(jù)不丟不重。

2. 作業(yè)的終結

流處理作業(yè)通常是長期運行的,但它們終有結束之時。結束的方式主要有三種:

(1) 成功完成:

  • 批處理模式:當所有輸入數(shù)據(jù)都被處理完畢后,作業(yè)會自然結束。Source算子會發(fā)送一個特殊的“結束”信號,信號傳遞到Sink后,所有任務正常退出,狀態(tài)為FINISHED。
  • 流處理模式:流作業(yè)理論上永不結束。它的“完成”通常是由用戶主動觸發(fā)的。例如,通過STOP命令(Savepoint后停止)或CANCEL命令。

(2) 失敗與重啟:

  • 故障發(fā)生:某個Task可能因為代碼異常、網(wǎng)絡問題、TaskManager宕機等原因而失敗。
  • 報告失敗:Task會向JobMaster報告失敗。
  • 重啟策略:JobMaster會根據(jù)配置的重啟策略(如固定延遲重啟、失敗率重啟)來決定是否重啟作業(yè)。
  • 恢復作業(yè):如果決定重啟,JobMaster會取消所有正在運行的任務,然后從最近一次成功的檢查點或保存點中恢復ExecutionGraph的狀態(tài),并重新調度所有任務。整個作業(yè)會像“時光倒流”一樣,回到一個一致的狀態(tài),然后重新開始處理。

(3) 用戶取消:

  • 用戶通過Flink Web UI或命令行工具(flink cancel <job_id>)向JobMaster發(fā)送取消請求。
  • JobMaster會向所有TaskManager發(fā)送取消信號。
  • TaskManager接收到信號后,會中斷正在運行的Task線程,并釋放所有資源(包括TaskSlot)。
  • JobMaster更新ExecutionGraph中所有ExecutionVertex的狀態(tài)為CANCELED,然后自己也退出。

無論以何種方式結束,JobMaster都會在退出前清理與該作業(yè)相關的所有資源,并將最終的作業(yè)狀態(tài)(FINISHED, FAILED, CANCELED)持久化,以便用戶查詢。

結論:從簡潔到強大的工程奇跡

回望這條Flink SQL的奇幻漂流,我們不禁為其背后設計的精妙與工程的復雜而感嘆。一行看似簡單的SQL,背后卻是一場涉及詞法語法解析、語義驗證、關系代數(shù)轉換、啟發(fā)式與成本優(yōu)化、物理算子映射、分布式作業(yè)圖構建、集群資源調度、并行任務執(zhí)行、網(wǎng)絡數(shù)據(jù)交換、狀態(tài)持久化與容錯恢復的宏大交響。

  • Apache Calcite作為其“大腦”,賦予了Flink SQL強大的解析和優(yōu)化能力,使其能夠像傳統(tǒng)數(shù)據(jù)庫一樣智能地處理查詢。
  • TableEnvironment作為其“中央處理器”,串聯(lián)起了從SQL到邏輯計劃的整個前端流程。
  • JobGraph作為其“設計藍圖”,架起了高級抽象與底層執(zhí)行之間的橋梁。
  • JobManager/TaskManager架構作為其“軀干”,提供了穩(wěn)定、高效、可擴展的分布式運行環(huán)境。
  • 檢查點機制作為其“免疫系統(tǒng)”,保證了在不可靠的分布式環(huán)境下的數(shù)據(jù)一致性。

Flink SQL的成功,在于它通過層層抽象,將用戶從繁瑣的底層實現(xiàn)中解放出來,讓他們能夠專注于業(yè)務邏輯本身。而當我們深入其內部,才發(fā)現(xiàn)這份簡潔的背后,是無數(shù)工程師智慧的結晶,是對分布式系統(tǒng)、編譯原理、數(shù)據(jù)庫理論等領域的深刻理解和巧妙運用。

理解了這條從SQL到運行的完整鏈路,我們不僅能更好地使用Flink SQL,寫出更高效的查詢,更能欣賞到現(xiàn)代大數(shù)據(jù)處理框架的內在之美。這趟旅程的終點,也是我們更深層次理解和運用Flink的起點。在數(shù)據(jù)之河奔流不息的未來,F(xiàn)link SQL這艘巨輪,將繼續(xù)憑借其強大的內核,載著我們駛向更廣闊的智能世界。

責任編輯:趙寧寧 來源: 大數(shù)據(jù)技能圈
相關推薦

2023-11-28 08:24:21

SQLredis

2023-10-06 15:29:07

MySQL數(shù)據(jù)庫更新

2021-06-15 10:46:51

HTTPS網(wǎng)絡協(xié)議TCP

2025-10-16 07:05:00

SparkSQLSpark 內核

2021-04-16 07:04:53

SQLOracle故障

2017-03-29 15:50:09

AndroidApp框架

2017-12-04 09:26:56

架構師碼農菜鳥

2018-09-14 14:20:43

人肉智能運維

2017-10-23 15:17:42

技術業(yè)務職位

2022-04-13 18:24:22

Nacos客戶端存儲

2020-05-26 09:08:23

命令循環(huán)Linux

2020-03-18 08:56:27

頁面網(wǎng)址內容

2023-10-30 23:14:57

瀏覽器URL網(wǎng)頁

2021-09-15 06:21:36

Update語句數(shù)據(jù)庫

2021-02-09 09:50:21

SQLOracle應用

2016-01-29 10:32:32

KDEKDE PlatforQt 框架

2019-01-07 09:15:10

BAT技術互聯(lián)網(wǎng)Java

2020-10-26 08:02:28

SQL慢查詢索引

2024-11-15 16:27:58

函數(shù)結構存儲

2020-12-09 08:12:30

系統(tǒng)架構
點贊
收藏

51CTO技術棧公眾號

亚洲欧美另类综合| 精品熟女一区二区三区| www.久久久久.com| 成人免费视频视频| 国产精品成人aaaaa网站| 日本黄区免费视频观看| 老司机亚洲精品一区二区| 香蕉成人啪国产精品视频综合网| 久久99精品久久久久久水蜜桃 | 岛国精品视频在线播放| 天天人人精品| 空姐吹箫视频大全| 日韩1区2区3区| 欧美极度另类性三渗透| 91网站免费视频| 色999久久久精品人人澡69| 亚洲午夜电影在线| 午夜精品短视频| 欧美熟妇乱码在线一区| 人人精品人人爱| 韩国一区二区电影| 国产黄a三级三级| 美女视频亚洲色图| 91精品国产91热久久久做人人| 妞干网在线视频观看| 日本中文字幕视频在线| 99久久伊人网影院| 亚洲一区二区自拍| 免费黄色一级大片| 国产精品综合| 欧美多人乱p欧美4p久久| 久久丫精品忘忧草西安产品| 成人h动漫免费观看网站| 欧美日韩国产在线观看| 18禁男女爽爽爽午夜网站免费| jizz性欧美| 欧美国产视频在线| 欧美在线日韩精品| 天天干天天做天天操| 日本人妖一区二区| 奇米成人av国产一区二区三区| 九九热精品免费视频| 日韩精品诱惑一区?区三区| 精品亚洲男同gayvideo网站| 性猛交╳xxx乱大交| 91国产一区| 欧美日韩一区二区在线观看| 成人亚洲视频在线观看| 一级毛片久久久| 精品欧美aⅴ在线网站| 欧美大黑帍在线播放| av在线免费播放| 最新不卡av在线| 伊人久久99| 欧美天天影院| 亚洲婷婷综合久久一本伊一区 | 欧美黄免费看| 欧美精品在线观看| www青青草原| 欧美成人久久| 欧美劲爆第一页| 国产精品第二十页| 亚洲第一黄色| 欧美一级电影久久| 亚洲综合图片网| 丝袜美腿亚洲一区| 国产精品视频免费在线观看| 伊人亚洲综合网| 久久99精品国产麻豆不卡| 国产三级精品网站| 国产三级漂亮女教师| 国产精品一区专区| 国产 高清 精品 在线 a| 亚洲国产精品suv| www..com久久爱| 久久精品国产精品国产精品污 | 九九热免费精品视频| 成人涩涩视频| 日韩一卡二卡三卡| 国内精品免费视频| 亚洲va久久| 在线电影av不卡网址| 91香蕉视频在线播放| 欧美在线精品一区| 77777少妇光屁股久久一区| 亚洲另类在线观看| 久久99国产精品免费网站| 97netav| 手机看片福利永久| 国产丝袜欧美中文另类| 成年人黄色在线观看| 国产一线二线在线观看 | 欧美成人手机在线| 日韩成人高清视频| 奇米精品一区二区三区四区| 成人精品在线观看| 免费观看黄一级视频| 久久精品视频网| 国产日韩欧美大片| 亚洲人成午夜免电影费观看| 欧美三级电影精品| 日本国产在线视频| 色777狠狠狠综合伊人| 欧美俄罗斯乱妇| 中文字幕乱码人妻无码久久| 成人精品电影在线观看| 亚洲成人一区二区三区| 国产蜜臀av在线播放| 欧美探花视频资源| 99久久国产精| 欧美一区二区三区另类| 国产成人精品久久二区二区| 亚洲经典一区二区三区| 国产欧美日韩视频在线观看| 亚洲 欧美 综合 另类 中字| 91九色综合| 亚洲国产成人精品女人久久久| 天堂网av2018| 久久伊人亚洲| 精品不卡在线| 在线观看午夜av| 欧美日韩一区二区不卡| 国产国语性生话播放| 欧美aⅴ99久久黑人专区| 国产精品啪视频| 免费理论片在线观看播放老| 午夜久久久影院| 日本女人性视频| 欧美成人激情| 国产精品久久久久9999| 桃花色综合影院| 亚洲线精品一区二区三区| 九色91popny| 狼人天天伊人久久| 欧美成aaa人片免费看| 少妇久久久久久久| 成人免费视频caoporn| 亚洲小视频在线播放| 成人在线网站| 日韩精品极品毛片系列视频| 一区二区视频免费看| 老司机精品视频网站| 操一操视频一区| 毛片在线播放a| 欧美亚洲一区三区| 亚洲欧美视频在线播放| 99亚洲伊人久久精品影院红桃| 亚洲999一在线观看www| 日本中文字幕在线视频| 欧美中文字幕亚洲一区二区va在线| 男男一级淫片免费播放| 五月激情久久久| 成人激情视频免费在线| 国产在线视频网站| 欧美色另类天堂2015| 国产高潮视频在线观看| 国产一区久久| av色综合网| 在线观看午夜av| 91精品国产欧美一区二区| 少妇高潮在线观看| 九九久久精品视频| 日韩精品欧美在线| 亚洲老司机网| 俺去啦;欧美日韩| 一级黄色片视频| 国产精品免费人成网站| 黄色手机在线视频| 欧美一区免费| 国产成人免费观看| 黑人极品ⅴideos精品欧美棵| 在线不卡欧美精品一区二区三区| 精品一区二区三孕妇视频| 奇米影视在线99精品| 国产一区一区三区| 国产999精品在线观看| 久久精品一本久久99精品| 一区二区国产欧美| 亚洲精选视频在线| 中文字幕无码毛片免费看| 欧美韩日精品| 久久久亚洲综合网站| gay欧美网站| 国产一区二区三区在线| 国产精品xxxxxx| 亚洲免费看黄网站| 91丨porny丨对白| 国产日韩欧美一区在线| 欧美12av| 久久久久久一区二区三区四区别墅| 欧美成人性色生活仑片| 国产综合在线播放| 色综合一区二区| 久久精品色妇熟妇丰满人妻| 黄页视频在线91| 青青草视频在线视频| 亚洲欧美校园春色| 国产欧美日韩精品丝袜高跟鞋| 三区四区电影在线观看| 欧美一卡二卡三卡四卡| 日本在线观看视频网站| 国产精品久久久久久亚洲毛片| 欧美又黄又嫩大片a级| 伊人影院久久| 欧美日韩一区二区三区免费| 视频在线亚洲| 国产aⅴ夜夜欢一区二区三区 | 免费看日韩毛片| 中文字幕日韩av资源站| 亚洲中文字幕无码一区| 日韩不卡一二三区| 欧美视频在线第一页| 亚洲三级网页| 国产精品视频入口| 三级成人在线| 欧美激情一区二区三级高清视频| 免费福利在线视频| 欧美一区二区三区影视| 中文字幕在线日亚洲9| 亚洲一区视频在线观看视频| 91激情视频在线观看| 成人福利视频在线看| 91视频最新入口| 欧美成人综合| 欧美成人综合一区| 亚洲超碰在线观看| 成人中文字幕+乱码+中文字幕| 免费一二一二在线视频| 久久国产精品视频| 午夜在线播放| 亚洲高清在线观看| 成人免费视频国产免费麻豆| 欧美色老头old∨ideo| 精品欧美一区二区三区免费观看| 国产精品国产精品国产专区不蜜| 国产高潮呻吟久久| 99精品视频在线观看| 亚洲天堂一区二区在线观看| 日韩精品一卡二卡三卡四卡无卡| 蜜臀精品一区二区| 亚洲无线一线二线三线区别av| 一区二区在线观看网站| 你懂的视频欧美| 精品欧美一区二区在线观看视频 | 日韩欧美国产激情| 中文字幕一区二区三区手机版| 国产精品白丝在线| 成人国产精品久久久网站| 久久精品亚洲一区二区三区浴池| 国产麻豆xxxvideo实拍| 丰满亚洲少妇av| xxxx国产视频| 高清shemale亚洲人妖| 9l视频白拍9色9l视频| 日韩精品每日更新| 欧美日韩在线不卡视频| 国产精品人人爽人人做我的可爱| 久久久999免费视频| 国产综合自拍| 青草视频在线观看视频| 中文字幕午夜精品一区二区三区| 法国空姐在线观看免费| 91精品蜜臀一区二区三区在线| 亚洲精品日韩成人| 日韩精品dvd| 在线观看欧美一区| 欧美日韩精选| 黄色一级片国产| 国产精品va| 黄色三级中文字幕| av成人天堂| 午夜肉伦伦影院| 丝袜亚洲另类欧美| 欧美婷婷精品激情| 久久99精品一区二区三区三区| 国产xxxxx视频| 国产在线精品一区二区| 91香蕉视频免费看| 国产超碰在线一区| 中文字幕在线永久| 亚洲国产成人自拍| 国产一区第一页| 一区二区高清视频在线观看| 精品无码久久久久久久久| 色播五月激情综合网| 亚洲中文字幕无码爆乳av| 欧美日韩在线播| av av片在线看| 精品国产一区二区三区久久久蜜月| 五月天久久久久久| 亚洲丝袜在线视频| 黄网站在线免费看| 久久这里有精品| 小视频免费在线观看| 国产精品你懂得| 国产一区2区在线观看| 91青青草免费在线看| 精品产国自在拍| 香港三级日本三级a视频| 午夜在线视频一区二区区别 | 激情小说亚洲一区| xxxxwww一片| 久久精品亚洲麻豆av一区二区| 日本性高潮视频| 亚洲va欧美va人人爽| 91视频在线视频| 日韩一区二区三区视频在线| 亚洲AV成人无码一二三区在线| 久久精品视频99| 成人av观看| 91网站在线免费观看| 首页亚洲中字| 97免费视频观看| 三级欧美在线一区| 伊人成人免费视频| 91丨九色丨蝌蚪富婆spa| 91嫩草|国产丨精品入口| 色综合久久久久| 性欧美一区二区三区| 亚洲女人被黑人巨大进入| 欧美大片黄色| 国产精品视频中文字幕91| 成人福利一区| 日本欧美精品久久久| 国产精品久久久久久久免费软件 | 欧美日韩国产网站| 91中文字幕在线观看| 在线视频亚洲专区| 免费人成在线观看视频播放| 久久91精品久久久久久秒播| 给我看免费高清在线观看| 亚瑟在线精品视频| 国产av一区二区三区| 尤物yw午夜国产精品视频| 91制片在线观看| 大波视频国产精品久久| 久久久久久久久国产一区| 国产精品亚洲二区在线观看| 国产另类ts人妖一区二区| 黄色香蕉视频在线观看| 在线中文字幕一区二区| 婷婷在线免费观看| 久久久极品av| 清纯唯美激情亚洲| 天天干天天操天天干天天操| 日韩高清电影一区| 亚洲精品国产熟女久久久| 精品日本高清在线播放| www.天天干.com| 精品国产欧美一区二区五十路| 日韩电影免费观看高清完整版在线观看| 欧美久久久久久| 国内精品久久久久久久影视麻豆 | www.黄在线观看| 97在线视频一区| 亚洲涩涩av| 久久国产乱子伦免费精品| 26uuu亚洲综合色| 国产精品久久久久久久久夜色| 亚洲激情视频网站| 国产99在线| 精品欧美日韩| 国产精品资源| 亚洲av无码国产精品麻豆天美| 色综合天天综合网天天狠天天 | 97人人做人人爽香蕉精品| 日韩av电影免费播放| 日韩综合一区二区| 日韩影视一区二区三区| 欧美精品电影在线播放| 免费在线午夜视频| 91色p视频在线| 欧美三级第一页| 国产麻豆剧传媒精品国产av| 欧美日韩国产一区中文午夜| 午夜成人鲁丝片午夜精品| 国产精品久久久av| 91超碰成人| 中文字幕99页| 色偷偷88欧美精品久久久| 精品999视频| 国产日韩在线观看av| 日韩午夜电影| 国产肥白大熟妇bbbb视频| 欧美私人免费视频| 午夜小视频福利在线观看| 91丝袜脚交足在线播放| 亚洲茄子视频| 免费在线观看成年人视频| 7777精品伊人久久久大香线蕉最新版| a视频在线观看免费| 国产精品美女xx| 美女网站色91| 久草成人在线视频| 日韩精品中文字幕久久臀| 伊人久久一区| 18禁网站免费无遮挡无码中文 | 欧美最大成人综合网| 国内不卡的二区三区中文字幕 | 91久久奴性调教|