當前位置:網站首頁>Flink-入門介紹

Flink-入門介紹

2021-08-19 17:42:33 Ainio

Flink


概述

Apache Flink 是一個框架和分布式處理引擎,用於在無邊界和有邊界數據流上進行有狀態的計算。Flink 能在所有常見集群環境中運行,並能以內存速度和任意規模進行計算

無界流

  • 有定義流的開始,但沒有定義流的結束

    • 持續產生數據
    • 數據需要持續處理+立刻處理
    • 以特定的順序攝取事件
    • 流處理
  • 就是流數據

有界流

  • 有定義流的開始, 也有定義流的結束

    • 可以攝取所有數據後再進行計算
    • 所有數據可以被排序, 不需要有序攝取
    • 批處理
  • 就是靜態數據

Apache Flink 擅長處理無界和有界數據集

  • 時間控制
  • 狀態化

部署應用到任意地方

  • Flink 集成了所有常見的集群資源管理器

    • Hadoop YARN
    • Apache Mesos
    • Kubernetes
  • 通過資源管理器特定(resource-manager-specific)的部署模式實現

  • 提交或控制應用程序的所有通信都是通過 REST 調用進行的

    • REST

      • REST代錶錶現層狀態轉移(representational state transfer)
      • 在設計API時,使用路徑定比特資源,方法定義操作,通過Content-Type和Accept來協商資源的類型
      • 就是一種調用規範

運行任意規模應用

  • 處理每天處理數萬億的事件
  • 應用維護幾TB大小的狀態
  • 應用在數千個內核上運行

利用內存性能

  • 任務狀態始終保留在內存中, 如果狀態大小超過內存, 那麼會保存在高效訪問的磁盤數據結構中
  • Flink 通過定期和异步地對本地狀態進行持久化存儲來保證故障場景下精確一次的狀態一致性。

API 和庫

流處理應用的基本組件

  • 框架控制流,狀態和時間的性能----决定---->流處理框架----决定---->應用程序的構建和執行

      • 基本要素
      • 任何類型數據流
    • 狀態(即n個中間結果, 可能對應的數據結構會不同)

      • 每一個具有一定複雜度的流處理應用都有狀態

        • 與特定算子相關聯
        • 不可誇算子讀取狀態
      • 應用狀態管理相關的特性支持

        • 多種狀態基礎類型

          • 根據數據結構的不同, 對應的狀態基礎類型也不同

            • 原子值---->value
            • 列錶---->list
            • 映射---->map
          • checkpoint檢查點

            • 有狀態流應用的一致檢查點,其實就是所有任務的狀態,在某個時間點的一份拷貝(一份快照);這個時間點,應該是所有任務都恰好處理完一個相同的輸入數據的時候
        • 精確一次語義

          • checkpoint 和故障恢複算法保證了故障發生後應用狀態的一致性
          • Flink 能够在應用程序發生故障時,對應用程序透明,不造成正確性的影響
        • 超大數據量狀態

        • 可彈性伸縮的應用

          • 可增可减
          • 支持有狀態應用的分布式橫向伸縮
      • 關於狀態的容錯的機制

        • Raw

          • 原生的, 自己編寫
        • Manage

          • Flink的一套完整機制
      • 注册狀態

        • 算子狀態(不常用)

          • 只有當前算子可以訪問

            • 只要在同一個分區, 算子狀態是相同的
          • 數據結構

            • 列錶狀態

              • 將狀態存儲為一個列錶, 重分配時由原狀態存儲機進行分配(效率高)
            • 聯合列錶狀態

              • 也是一個列錶, 但是由新增後的機器選取狀態列錶(效率低)
            • 廣播狀態

              • 一個算子的多個並行子任務, 如果要求各個子任務狀態相同, 那麼就需要這種
        • 鍵控狀態Keyed State

          • 只有當前key可以訪問

          • 每一個Key維持一個狀態

          • 類型

            • 值狀態
            • 列錶狀態
            • 映射狀態
            • 聚合狀態
        • 狀態後端

          • 用於狀態的存儲,訪問,維護的組件

          • 可插入組件

          • 任務

            • 管理本地狀態
            • 管理checkpoint
          • 類型

            • MemoryStateBackend

              • 內存級的狀態後端

              • 將鍵控狀態作為內存中的對象進行管理

                • 存儲在TaskManager的JVM堆
              • checkpoint

                • 存儲在JobManager的內存中
              • 特點

                • 低延遲

                • 不穩定

                  • 假如JobManager掛了....
            • FsStateBackend(默認)

              • 本地狀態

                • 存在TaskManager的JVM堆
              • checkpoint

                • 存到遠程的持久化文件系統(FileSystem)上

                  • HDFS...
              • 速度快, 並且可擴展

            • RocksDBStateBackend

              • 將所有狀態序列化後,存入本地的RocksDB中存儲
              • RockDB是一個Facebook的數據庫
              • 需要訪問硬盤, 速度會慢, 但是穩定
            • 不同的Job可以分別靈活設置自己的狀態存儲策略

            • 重啟策略

              • region

                • 只重啟掛掉的機器
    • 時間

      • 流處理的重要組成部分

      • 大多數事件流都有事件本身固有的時間語義

        • 例如

          • 窗口聚合
          • 會話計算
          • 模式檢測
          • 基於時間的join
      • 衡量時間

        • 事件時間(event-time)
        • 處理時間(processiong-time)
      • 時間相關的語義支持

        • 事件時間模式

          • 根據事件本身自帶的時間戳進行結果的計算

            • 所以, 無論是曆史記錄還是實時處理, 結果都一樣
        • 處理時間模式

          • 根據處理引擎的機器時鐘觸發計算

            • 低延遲
            • 小誤差
        • Watermark(水印) 支持

          • 用於衡量事件時間進展

          • 好處

            • 平衡了處理延時(效率)和完整性(可用)
        • 遲到數據處理

          • 遲到事件

            • 當以帶有 watermark 的事件時間模式處理數據流時,在計算完成之後仍會有相關數據到達。
          • 多種處理機制

            • 將這些數據重定向到旁路輸出(side output)
            • 更新之前完成計算的結果

數據管道 & ETL(抽取、轉換、加載)

  • 無狀態的轉換

    • map()

      • 適用於一對一的轉換

        • 對每個進入算子的流元素,map() 將僅輸出一個轉換後的元素。
    • flatmap()

      • 使用接口中提供的 Collector ,flatmap() 可以輸出你想要的任意數量的元素,也可以一個都不發。
      • 一變多(打散)
    • Filter()

      • 過濾
  • Keyed Streams

    • keyBy()

rides .flatMap(new NYCEnrichment()) .keyBy(enrichedRide -> enrichedRide.startCell)

  • 使所有具有相同屬性的事件分到相同的組裏

  • 每個 keyBy 會通過 shuffle 來為數據流進行重新分區。總體來說這個開銷是很大的,它涉及網絡通信、序列化和反序列化

    • 通過計算得到鍵
keyBy(ride -> GeoUtils.mapToGridCell(ride.startLon, ride.startLat))
  • Keyed Stream 的聚合

  • (隱式的)狀態

    • 考慮狀態的大小

      • 如果鍵值的數量是無限的,那 Flink 的狀態需要的空間也同樣是無限的。
      • 在流處理場景中,考慮有限窗口的聚合往往比整個流聚合更有意義
  • reduce() 和其他聚合算子

    • reduce() 函數

      • 實現自定義聚合
  • 有狀態的轉換

    • 為什麼要狀態管理?

      • 本地性: Flink 狀態是存儲在使用它的機器本地的,並且可以以內存訪問速度來獲取
      • 持久性: Flink 狀態是容錯的,例如,它可以自動按一定的時間間隔產生 checkpoint,並且在任務失敗後進行恢複
      • 縱向可擴展性: Flink 狀態可以存儲在集成的 RocksDB 實例中,這種方式下可以通過增加本地磁盤來擴展空間
      • 橫向可擴展性: Flink 狀態可以隨著集群的擴縮容重新分布
      • 可查詢性: Flink 狀態可以通過使用 狀態查詢 API 從外部進行查詢。
    • Rich Functions

      • FilterFunction, MapFunction,和 FlatMapFunction

        • 單一抽象方法模式
      • “rich” 的變體

        • 增加了以下方法

          • open(Configuration c)

            • 算子初始化時調用一次
            • 可以用來加載一些靜態數據,或者建立外部服務的鏈接等
          • close()

          • getRuntimeContext()

            • 創建和訪問 Flink 狀態的途徑
    • 清理狀態

      • keyHasBeenSeen.clear()
    • Non-keyed State

  • Connected Streams

    • 更靈活地調整轉換的某些功能

      • 比如數據流的閾值、規則或者其他參數
    • 一個單獨的算子有兩個輸入流

    • 實例

  public static void main(String[] args) throws Exception {
    StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

    DataStream<String> control = env
        .fromElements("DROP""IGNORE")
        .keyBy(x -> x);

    DataStream<String> streamOfWords = env
        .fromElements("Apache""DROP""Flink""IGNORE")
        .keyBy(x -> x);
  
    control
        .connect(streamOfWords)
        .flatMap(new ControlFunction())
        .print();

    env.execute();
}
  • 注意兩個流只有鍵一致的時候才能連接

  • 兩個流中所有鍵相同的事件發到同一個實例上

分層API

  • 分層依據: 抽象程度

    • ProcessFunction(events,state,time)

      • ProcessFunction 可以處理一或兩條輸入數據流中的單個事件或者歸入一個特定窗口內的多個事件

      • 細粒度

        • 狀態

          • 狀態可以保存, 用於後續程序讀取前面已發生的狀態, 進行相應的處理

          • ValueState

            • 最基礎的狀態類型

            • 能够為被其封裝的變量添加容錯能力的類型

            • 一種 keyed state

              • 只能用於keyBy的DataStream
    • DataStream API

      • 提供通用的流操作的處理原語

        • 窗口/逐條記錄的轉換
        • 外部數據庫查詢
        • 等等
      • Java/Scala

      • 已定義的函數

        • reduce()
        • aggregate()
        • map()
        • 等等
    • SQL & Table API

      • 在無邊界的實時數據流和有邊界的曆史記錄數據流上,關系型 API 會以相同的語義執行查詢, 並產生相同的結果
      • Table API 和 SQL 借助了 Apache Calcite 來進行查詢的解析,校驗以及優化。它們可以與 DataStream 和 DataSet API 無縫集成,並支持用戶自定義的標量函數,聚合函數以及錶值函數

  • Flink 具有數個適用於常見數據處理應用場景的擴展庫

    • 可擴展
    • 非完全獨立(包含其他API)
  • 類型

    • 複雜事件處理(CEP)

      • 模式檢測

      • 應用範圍

        • 網絡入侵檢測
        • 業務流程監控
        • 欺詐檢測
    • Data Set API

      • 用於批處理

      • 基礎算子

        • map、reduce、(outer) join、co-group、iterate等
      • 算法

        • 混合散列連接(hybrid hash-join)
        • 外部歸並排序(external merge-sort)
    • Gelly

      • 可擴展的圖形處理和分析庫

      • 實現並集成在DataSet API之上

      • 內置算法

        • label propagation、triangle enumeration 和 page rank 算法
        • Graph API

運維

7 * 24小時穩定運行

  • 故障時重啟

  • 故障時保證能够持久化服務內部各個組件狀態狀態

    • 狀態持久化
  • 可持續性與一致性維護機制

    • 檢查點的一致性

      • 應用服務會重啟後,再重新加載上一次成功備份的狀態檢查點信息
      • 保證精確一次(exactly-once)的狀態一致性
    • 高效的檢查點

      • Flink采用异步及增量的方式構建檢查點服務

        • 解决狀態信息數據量過大以及延遲高的問題
    • 端到端的精確一次

      • 事務型輸出
    • 集成多種集群管理服務

      • Hadoop YARN, Mesos, 以及 Kubernetes
    • 內置高可用服務

      • 解决單點故障區問題

        • 基於ZooKeeper

Flink能够更方便地昇級、遷移、暫停、恢複應用服務

  • Savepoint保存點(快照)

    • 和checkpoint相似, 但是savepoint需要手動啟動, 並且當流應用服務停止時, 不會自動删除

    • 用處

      • Savepoint 常被應用於啟動一個已含有狀態的流服務,並初始化其(備份時)狀態
      • 就是初始化狀態(類似一鍵安裝的東西)
    • 特點

      • 便於昇級應用服務版本
      • 方便集群服務移植
      • 方便Flink版本昇級
      • 增加應用並行服務的擴展性
      • 便於A/B測試及假性分析場景對比結果
      • 暫停/恢複服務
      • 歸檔服務

監控和控制應用服務

  • Flink與許多常見的日志記錄和監視服務集成得很好,並提供了一個REST API來控制應用服務和查詢應用信息

    • Web UI方式

      • Flink提供了一個web UI來觀察、監視和調試正在運行的應用服務。並且還可以執行或取消組件或任務的執行。
    • 日志集成服務

      • Flink實現了流行的slf4j日志接口,並與日志框架log4j或logback集成
    • 指標服務

      • Flink提供了一個複雜的度量系統來收集和報告系統和用戶定義的度量指標信息。度量信息可以導出到多個報錶組件服務,包括 JMX, Ganglia, Graphite, Prometheus, StatsD, Datadog, 和 Slf4j
    • 標准的WEB REST API接口服務

      • Flink提供多種REST API接口,有提交新應用程序、獲取正在運行的應用程序的Savepoint服務信息、取消應用服務等接口。REST API還提供元數據信息和已采集的運行中或完成後的應用服務的指標信息。

應用場景

事件驅動型應用

  • 概念

    • 事件驅動型應用是一類具有狀態的應用,它從一個或多個事件流提取數據,並根據到來的事件觸發計算、狀態更新或其他外部動作。

      • 通俗說: 當發生了XXX事件時進行XXX的動作的應用
  • 應用從本地(內存/磁盤)訪問獲取數據

    • 數據和計算不分離
  • 容錯性

    • 定期向遠程持久化存儲寫入checkpoint
  • 優勢

    • 無須查詢遠程數據庫

    • 更高的吞吐和更低的延遲

    • 只需考慮自身數據

      • 協調工作將大大减少
  • Flink 如何支持事件驅動型應用?

    • 一系列豐富的狀態操作原語

      • ProcessFunction

        • 細粒度時間控制,方便實現一些高級業務邏輯
      • 複雜事件處理(CEP)類庫

        • 用來檢測數據流中的模式
    • savepoint

      • 用來初始化任意狀態兼容的應用
      • 在完成一次 savepoint 後,即可放心對應用昇級或擴容,還可以啟動多個版本的應用來完成 A/B 測試

數據分析應用

  • 概念

    • 數據分析任務需要從原始數據中提取有價值的信息和指標。

    • 實時地進行數據分析

      • 隨著事件消費持續產生和更新結果
    • 結果數據可能會寫入外部數據庫系統或以內部狀態的形式維護

  • 優勢

    • 省掉了周期性的數據導入和查詢過程

      • 獲取指標的延遲更低

      • 簡化應用抽象

        • 流式分析應用整體運行在 Flink 之類的高端流處理系統之上,涵蓋了從數據接入到連續結果計算的所有步驟,因此可以依賴底層引擎提供的故障恢複機制
  • Flink 如何支持數據分析類應用?

    • SQL 接口

      • 將批、流查詢的語義統一起來

        • 查詢結果一樣
    • 支持豐富的用戶自定義函數

      • 允許在 SQL 中執行定制化代碼
    • 利用 Flink DataStream API 和 DataSet API 進行更低層次的控制

    • Gelly 庫

數據管道應用

  • 概念

    • 提取-轉換-加載(ETL)是一種在存儲系統之間進行數據轉換和遷移的常用方法

    • ETL 作業通常會周期性地觸發,將數據從事務型數據庫拷貝到分析型數據庫或數據倉庫

    • 以持續流模式運行

      • 支持從一個不斷生成數據的源頭讀取記錄,並將它們以低延遲移動到終點
  • 優勢

    • 可以明顯降低將數據移動到目的端的延遲
    • 能够持續消費和發送數據
  • Flink 如何支持數據管道應用?

    • Flink 的 SQL 接口

    • Table API

    • 用戶自定義函數

    • DataStream API

    • Flink 為多種數據存儲系統內置了連接器

      • 如:Kafka、Kinesis、Elasticsearch、JDBC數據庫系統等)
    • 提供了文件系統的連續型數據源及數據匯,可用來監控目錄變化和以時間分區的方式寫入文件

實踐

目標

  • 實現可擴展並行度的ETL,數據分析,事件驅動的流式應用程序
  • 如何實現流數據處理管道(pipelines)
  • Flink 如何管理狀態以及為何需要管理狀態
  • 如何使用事件時間(event time)來一致並准確地進行計算分析
  • 如何在源源不斷的數據流上構建事件驅動的應用程序
  • Flink 如何提供具有精確一次(exactly-once)計算語義的可容錯、有狀態流處理

流處理

  • 應用程序(就是一堆處理方法, 簡稱算子)

    • 由用戶自定義算子(operator, DAG途中每塊都是一個算子)轉換而來的流式dataflows組成

    • 這些流式 dataflows 形成了有向圖,以一個或多個源(source)開始,並以一個或多個匯(sink下沉)結束

    • 並行Dataflows

      • 算子子任務數就是對應算子的並行度
    • 算子之間傳輸數據

      • 一對一模式

        • 例如上圖中的 Source 和 map() 算子之間
        • map() 算子的 subtask[1] 輸入的數據以及其順序與 Source 算子的 subtask[1] 輸出的數據和順序完全相同,即同一分區的數據只會進入到下遊算子的同一分區
      • 重新分發模式

        • 例如上圖中的 map() 和 keyBy/window 之間,以及 keyBy/window 和 Sink 之間

        • 當你在程序中選擇使用不同的 transformation,每個算子子任務也會根據不同的 transformation 將數據發送到不同的目標子任務

          • keyBy()(通過散列鍵重新分區)、broadcast()(廣播)或 rebalance()(隨機重新分發)
        • 重新分發數據的過程中,元素只有在每對輸出和輸入子任務之間才能保留其之間的順序信息

          • 例如,keyBy/window 的 subtask[2] 接收到的 map() 的 subtask[1] 中的元素都是有序的
        • 不同鍵(key)的聚合結果到達 Sink 的順序是不確定的

  • 自定義時間流處理

    • 使用記錄在數據流中的事件時間的時間戳,而不是處理數據的機器時鐘的時間戳
  • 有狀態流處理

    • 應用場景

      • 統計儀錶板上每分鐘顯示的數據
      • 訓練作弊檢測模型
    • 有狀態算子的並行實例組在存儲其對應狀態時通常是按照鍵(key)進行分片存儲的

      • 每個並行實例算子負責處理一組特定鍵的事件數據,並且這組鍵對應的狀態會保存在本地
    • 存儲比特置

      • 狀態訪問在本地執行

        • JVM堆
        • 高速磁盤(以結構化數據格式)
    • 實例

      • 前三個算子的並行度為 2,最後一個 sink 算子的並行度為 1,其中第三個算子是有狀態的

      • 第二個算子和第三個算子之間是全互聯的(fully-connected)

        • 通過網絡進行數據分發
        • 根據某些鍵對數據分區, 方便各個部分的狀態記錄, 每個部分統一計算處理
  • 通過狀態快照實現的容錯

    • 通過狀態快照和流重放兩種方式的組合,Flink 能够提供可容錯的,精確一次計算的語義。

    • 狀態快照在執行時會獲取並存儲分布式 pipeline 中整體的狀態

      • 它會將數據源中消費數據的偏移量記錄下來,並將整個 job graph 中算子獲取到該數據(記錄的偏移量對應的數據)時的狀態記錄並存儲下來

版權聲明
本文為[Ainio]所創,轉載請帶上原文鏈接,感謝
https://cht.chowdera.com/2021/08/20210819174232389j.html

隨機推薦