精品欧美一区二区三区在线观看 _久久久久国色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技術棧公眾號

成年女人18级毛片毛片免费| 欧美中文字幕精品| 中文字幕人妻熟女人妻a片| 污污视频在线| 久久综合色综合88| 国产精品一区二区女厕厕| 黄色片子在线观看| 日韩av网站在线免费观看| 欧美性色黄大片手机版| 17c丨国产丨精品视频| 玖玖综合伊人| 高潮精品一区videoshd| 日本精品一区二区三区在线| 国产67194| 蜜桃精品wwwmitaows| 51精品国自产在线| 国产男女无遮挡| 牛牛在线精品视频| 中文字幕av在线一区二区三区| 999在线观看免费大全电视剧| 国产精品500部| 婷婷久久国产对白刺激五月99| 亚洲国产中文字幕久久网| 手机免费av片| 精品亚洲美女网站| 亚洲国产日韩a在线播放| 亚洲欧洲精品一区| 邻居大乳一区二区三区| 99视频在线观看一区三区| 91手机视频在线观看| 亚洲婷婷久久综合| 国产精品美女久久久浪潮软件| 久久天天躁狠狠躁夜夜爽蜜月| 欧美激情aaa| 欧美久久香蕉| 欧美高清hd| 成人国产电影网| 91久久精品国产| 中文字幕免费播放| 美女国产一区| 57pao成人国产永久免费| 国产亚洲欧美久久久久| 中文字幕日韩一区二区不卡| 最新69国产成人精品视频免费| 久久无码人妻精品一区二区三区| 成人福利一区| 日韩欧美一区在线| 欧美色图校园春色| 久久伊人久久| 日韩视频在线一区二区| av噜噜在线观看| 日韩专区视频| 91麻豆精品国产91久久久久| 91丨九色丨蝌蚪| 91麻豆精品| 欧美一区欧美二区| 国产伦精品一区二区三区妓女下载 | 欧洲亚洲精品久久久久| 欧美亚洲一区二区三区四区| 久久久久久久久久久久久国产精品| 黑森林国产精品av| 精品国产福利在线| 日韩免费视频播放| 中文字幕高清在线播放| 色综合天天综合狠狠| 精品免费国产一区二区| 亚洲欧美在线成人| 欧美美女一区二区在线观看| 在线看免费毛片| 精品一区二区三区中文字幕在线| 日韩欧美国产高清| 日韩av无码一区二区三区不卡| 青青操综合网| 国产一区二区三区直播精品电影| 欧美老女人性生活视频| 99久久夜色精品国产亚洲96| 久久综合色88| 日本亚洲色大成网站www久久| 色av性av丰满av| 成人在线免费观看视频| 久久久国产精品x99av| 亚洲成人生活片| 在线国产精品一区| 国产成人一区二区三区| 91国产免费视频| 成人免费毛片a| 青青草成人网| 高潮毛片在线观看| 黄色一区二区在线观看| 99视频在线视频| 亚洲精品一二三**| 亚洲美女又黄又爽在线观看| 极品尤物一区二区| 精品999网站| 国产精品高潮在线| 午夜精品久久久久久久第一页按摩 | 免费视频最近日韩| 91久久伊人青青碰碰婷婷| 天堂av一区二区三区| 亚洲国产精品成人综合| 欧美一级中文字幕| 日韩久久一区二区三区| 日韩精品一区二| 91精品国自产在线| 亚洲欧洲视频| 成人两性免费视频| 男人的天堂在线视频| 亚洲乱码中文字幕| 韩国日本在线视频| 高清日韩中文字幕| 日韩小视频在线| 日韩精品一区二区亚洲av| 国产毛片一区二区| 性欧美.com| 日韩理论视频| 欧美成人官网二区| 一区二区国产精品精华液| 天堂av在线一区| 国产视频在线观看一区| av大片在线| 欧美日韩国产高清一区二区| 97人人澡人人爽| 乱老熟女一区二区三区| 国产精品一国产精品k频道56| 亚洲aaaaaa| 3p在线观看| 色综合久久久久| 国产又粗又长又爽| 狠久久av成人天堂| 亚洲va欧美va在线观看| 北岛玲一区二区三区| 欧美午夜激情在线| 韩国一区二区三区四区| 久久精品影视| 国产欧美一区二区三区在线看| 日本国产在线| 天天做天天摸天天爽国产一区| 男人的天堂免费| 亚洲xxx拳头交| 国产欧美日韩中文| 国产高清一级毛片在线不卡| 欧美日韩综合视频| 国产精品无码永久免费不卡| 99国产精品| 激情小说综合网| 久热精品视频在线免费观看| 亚洲一级av毛片| 国产精品丝袜在线| 香港日本韩国三级网站| 日韩电影免费在线观看| 国产精品网址在线| 五月香视频在线观看| 欧美日韩aaaaa| 免费在线观看黄色小视频| 精品一区二区久久久| 正在播放国产精品| 成人在线视频国产| 欧美国产日韩精品| 秋霞av鲁丝片一区二区| 精品久久久久久久久久久| 国产精品久久久免费观看| 国产美女一区| 日韩aⅴ视频一区二区三区| 成人深夜福利| 久久的精品视频| 亚洲精选一区二区三区| 激情av一区二区| 女人又爽又黄免费女仆| 麻豆国产欧美一区二区三区| 色香蕉在线观看| jazzjazz国产精品麻豆| 日本中文字幕不卡免费| 97最新国自产拍视频在线完整在线看| 性娇小13――14欧美| 亚洲国产精品久久久久秋霞不卡| 日本熟妇一区二区| 国产亚洲制服色| 国内av一区二区| 99精品国产福利在线观看免费| 美乳视频一区二区| 国产欧美自拍| 国内外成人免费激情在线视频| 每日更新在线观看av| 欧美日韩国产精选| 亚欧洲精品在线视频| 国产亚洲女人久久久久毛片| 激情文学亚洲色图| 亚洲激情综合| 亚洲一区二三| 欧美深夜视频| 91精品视频免费看| 在线中文字幕播放| 另类美女黄大片| 你懂的免费在线观看视频网站| 欧美日韩国产欧美日美国产精品| 国产在线观看免费av| 中文字幕欧美国产| 天堂www中文在线资源| 日本午夜一区二区| 国产精品入口芒果| 日韩欧美一区免费| 蜜桃久久影院| 看亚洲a级一级毛片| 日韩美女av在线免费观看| 综合图区亚洲| 最近2019中文字幕在线高清| 免费观看黄色一级视频| 欧美日韩不卡一区二区| 中文字幕av影院| 亚洲一区二区三区自拍| 超碰97av在线| 国产亚洲一区二区三区在线观看 | 国产一级二级三级| 国产精品不卡在线| 国产全是老熟女太爽了| 粉嫩av一区二区三区粉嫩 | 欧美成人一二区| 全球成人中文在线| 538在线视频| 欧美老少配视频| 午夜视频在线免费观看| 亚洲视频在线看| 色欲久久久天天天综合网| 欧美一区二区三区日韩| 中文字幕男人天堂| 色8久久人人97超碰香蕉987| 懂色av.com| 国产黄色在线免费观看| 91精品国产综合久久久久久 | 51精品国自产在线| 中文字幕在线视频免费| 色哟哟一区二区在线观看| 日本中文字幕免费观看| 亚洲一区自拍偷拍| 欧美激情国产精品免费| 亚洲欧美国产高清| 欧美激情精品久久久久久免费| 国产精品视频第一区| 天天操天天干天天操天天干| 国产日韩综合av| 欧美三级视频网站| 久久久精品综合| 欧美日韩高清丝袜| 国产午夜精品一区二区三区视频| 大地资源二中文在线影视观看| 91首页免费视频| 国产国语性生话播放| 91视频www| 欧美日韩高清丝袜| 中文字幕乱码一区二区免费| 少妇av片在线观看| 中文av一区二区| 黄色录像免费观看| 亚洲激情男女视频| 久久久久久久极品内射| 亚欧色一区w666天堂| 日本道在线观看| 日本道精品一区二区三区| 国产成人av免费| 欧美日韩精品欧美日韩精品一综合| 亚洲国产无线乱码在线观看| 欧美日本国产一区| 99久久精品国产色欲| 欧美精品一区二区在线播放| 天天爱天天干天天操| 亚洲人午夜精品| porn视频在线观看| 欧美xxxx18性欧美| 俄罗斯一级**毛片在线播放| 国产91精品久| 日韩一级二级| 91一区二区三区| 亚洲人成网亚洲欧洲无码| 四虎一区二区| 亚洲午夜精品一区二区国产| 国产精品国产亚洲精品看不卡| 亚洲免费中文| 天堂av8在线| www.亚洲免费av| 日本乱子伦xxxx| 伊人开心综合网| 欧美a∨亚洲欧美亚洲| 欧美日韩综合色| 亚洲伦理在线观看| 亚洲一品av免费观看| av毛片在线| 国产精品88a∨| 6080成人| 相泽南亚洲一区二区在线播放| 日本啊v在线| 国产嫩草影院久久久久| 日本中文字幕免费在线观看| 精品福利免费观看| 一本色道久久综合熟妇| 亚洲精品电影在线| 欧美午夜电影一区二区三区| 国内精品视频在线| 羞羞视频在线观看一区二区| 精品无人区一区二区三区竹菊| 99久久国产综合精品成人影院| 日韩欧美一区二| 国内成人免费视频| 久久精品国产亚洲av麻豆| 亚洲男人天堂av| 日本丰满少妇做爰爽爽| 精品女同一区二区| 午夜毛片在线| 日韩美女免费观看| h视频久久久| 美女在线免费视频| 美女视频网站黄色亚洲| 国产亚洲色婷婷久久99精品91| 国产精品福利一区| 欧美一级做a爰片免费视频| 成人免费视频一区| 亚洲一卡二卡三卡| 亚洲免费影院| 国产精久久久久| 亚洲欧洲国产专区| 国产一级片av| 亚洲免费电影在线观看| 麻豆蜜桃在线| 亚洲free嫩bbb| 久久精品高清| 无码日韩人妻精品久久蜜桃| 91日韩一区二区三区| 精品在线免费观看视频| 91精品国产综合久久福利| 69视频在线| 国产精品视频网| 精品国产精品| 黄色动漫在线免费看| av日韩在线网站| 国产一卡二卡在线播放| 欧美mv和日韩mv国产网站| 制服丝袜中文字幕在线| 亚洲综合在线播放| 91超碰成人| 亚洲一级片免费观看| 综合久久久久久| 国产男男gay体育生网站| xvideos成人免费中文版| 成人在线视频观看| 五月天亚洲综合小说网| 日本va欧美va精品发布| 一级片久久久久| 欧美精品高清视频| 黄色在线论坛| 91九色蝌蚪成人| 黄页网站一区| 粉嫩av懂色av蜜臀av分享| 欧美日韩激情视频| 免费成人av电影| 国产精品久久久久久久久借妻| 久久av电影| 欧美日韩中文不卡| 亚洲色图都市小说| av网站在线观看免费| 欧美激情在线播放| 秋霞蜜臀av久久电影网免费| 国产成人在线免费看| 久久久久久久久久久久久女国产乱| 成人av网站在线播放| 色哟哟亚洲精品一区二区| 高清一区二区| 激情五月六月婷婷| 99riav久久精品riav| 91丨九色丨海角社区| 不卡伊人av在线播放| 九九热hot精品视频在线播放| 日韩中文字幕在线视频观看| 久久久国产精品午夜一区ai换脸| 伊人精品一区二区三区| 久久视频在线视频| 加勒比久久高清| 欧美大尺度做爰床戏| 亚洲日穴在线视频| 污视频在线免费观看| 国产精品普通话| 韩国久久久久| 国产美女免费网站| 91精品国产综合久久久久久久久久 | 亚洲国产欧美国产第一区| 亚洲熟妇无码另类久久久| 国产欧美一区二区三区在线看蜜臀| 国产精品免费无遮挡| 久久久中精品2020中文| 精品国产网站| 国产男女无遮挡猛进猛出| 亚洲国产精品一区二区尤物区| 国产尤物视频在线| 91免费版黄色| 老司机午夜精品视频在线观看| 四虎永久免费地址| 日韩高清欧美高清| 国产电影一区二区| 国产淫片av片久久久久久| 亚洲精品免费在线| 国产精品秘入口| 国产综合色一区二区三区|