1. 跟着官網學 Apache Flink 1.10.0 之理論篇

0x01 前言

如今早已進入信息大爆炸時代, 每天我們的生活都會伴隨着海量數據的產生: 信用卡交易、傳感器測量、機器日誌、網站或移動應用程序上的用戶交互記錄。

針對這些海量數據處理, 如果還使用傳統的數據處理方式,將會變得及其緩慢和低效。

爲此,我們需要引入分佈式存儲, 分佈式搜索,分佈式計算,分佈式事務,分佈式緩存,分佈式架構等一系列技術來解決相關問題。

爲了更方便地使用這些技術, Java 後端生態出現了很多優秀的大數據處理框架,比如支持批處理的框架Apache Hadoop, 流處理的框架Apache Storm,流處理和批處理都支持的Apache Spark, Apache Flink.

0x02 跟着官網學 Apache Flink 1.10.0 之理論篇程

這節課我們來學習Apache Flink 框架。

1.1 什麼是Apache Flink?

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

1.1.1 架構

1.1.1.1 處理無界和有界數據

任何類型的數據都可以形成一種事件流。 信用卡交易、傳感器測量、機器日誌、網站或移動應用程序上的用戶交互記錄,所有這些數據都形成一種流。

數據可以被作爲 無界 或者 有界 流來處理。

  • 無界流
    有定義流的開始,但沒有定義流的結束。它們會無休止地產生數據。無界流的數據必須持續處理,即數據被攝取後需要立刻處理。我們不能等到所有數據都到達再處理,因爲輸入是無限的,在任何時候輸入都不會完成。處理無界數據通常要求以特定順序攝取事件,例如事件發生的順序,以便能夠推斷結果的完整性。
  • 有界流
    有定義流的開始,也有定義流的結束。有界流可以在攝取所有數據後再進行計算。有界流所有數據可以被排序,所以並不需要有序攝取。有界流處理通常被稱爲批處理

在這裏插入圖片描述
Apache Flink 擅長處理無界和有界數據集 精確的時間控制和狀態化使得 Flink 的運行時(runtime)能夠運行任何處理無界流的應用。有界流則由一些專爲固定大小數據集特殊設計的算法和數據結構進行內部處理,產生了出色的性能。

1.1.1.2 部署應用到任意地方

  • Apache Flink 是一個分佈式系統,它需要計算資源來執行應用程序。Flink 集成了所有常見的集羣資源管理器,例如 Hadoop YARN、 Apache Mesos 和 Kubernetes,但同時也可以作爲獨立集羣運行。
  • Flink 被設計爲能夠很好地工作在上述每個資源管理器中,這是通過資源管理器特定(resource-manager-specific)的部署模式實現的。Flink 可以採用與當前資源管理器相適應的方式進行交互。
  • 部署 Flink 應用程序時,Flink 會根據應用程序配置的並行性自動標識所需的資源,並從資源管理器請求這些資源。在發生故障的情況下,Flink通過請求新資源來替換髮生故障的容器。提交或控制應用程序的所有通信都是通過 REST 調用進行的,這可以簡化 Flink 與各種環境中的集成

1.1.1.3 運行任意規模應用

Flink旨在任意規模上運行有狀態流式應用。因此,應用程序被並行化爲可能數千個任務,這些任務分佈在集羣中併發執行。所以應用程序能夠充分利用無盡的 CPU、內存、磁盤和網絡 IO。而且 Flink很容易維護非常大的應用程序狀態。其異步和增量的檢查點算法對處理延遲產生最小的影響,同時保證精確一次狀態的一致性。

  • Flink 用戶報告了其生產環境中一些令人印象深刻的擴展性數字
    • 處理每天處理數萬億的事件,
    • 應用維護幾TB大小的狀態,
    • 應用在數千個內核上運行。

1.1.1.4 利用內存性能

有狀態的 Flink程序針對本地狀態訪問進行了優化。任務的狀態始終保留在內存中,如果狀態大小超過可用內存,則會保存在能高效訪問的磁盤數據結構中。任務通過訪問本地(通常在內存中)狀態來進行所有的計算,從而產生非常低的處理延遲。Flink 通過定期和異步地對本地狀態進行持久化存儲來保證故障場景下精確一次的狀態一致性。
在這裏插入圖片描述

1.1.2 應用

Apache Flink 是一個針對無界和有界數據流進行有狀態計算的框架。Flink 自底向上在不同的抽象級別提供了多種 API,並且針對常見的使用場景開發了專用的擴展庫。

在本章中,我們將介紹 Flink 所提供的這些簡單易用、易於表達的 API 和庫。

1.1.2.1 流處理應用的基本組件

可以由流處理框架構建和執行的應用程序類型是由框架對 流、狀態、時間 的支持程度來決定的。在下文中,我們將對上述這些流處理應用的基本組件逐一進行描述,並對 Flink 處理它們的方法進行細緻剖析。

1.1.2.1.1 流

顯而易見,(數據)流是流處理的基本要素。然而,流也擁有着多種特徵。這些特徵決定了流如何以及何時被處理。Flink 是一個能夠處理任何類型數據流的強大處理框架

  • 有界 和 無界 的數據流:流可以是無界的;也可以是有界的,例如固定大小的數據集。Flink 在無界的數據流處理上擁有諸多功能強大的特性,同時也針對有界的數據流開發了專用的高效算子。
  • 實時 和 歷史記錄 的數據流:所有的數據都是以流的方式產生,但用戶通常會使用兩種截然不同的方法處理數據。或是在數據生成時進行實時的處理;亦或是先將數據流持久化到存儲系統中——例如文件系統或對象存儲,然後再進行批處理。Flink 的應用能夠同時支持處理實時以及歷史記錄數據流。
1.1.2.1.2 狀態

只有在每一個單獨的事件上進行轉換操作的應用纔不需要狀態,換言之,每一個具有一定複雜度的流處理應用都是有狀態的。任何運行基本業務邏輯的流處理應用都需要在一定時間內存儲所接收的事件或中間結果,以供後續的某個時間點(例如收到下一個事件或者經過一段特定時間)進行訪問並進行後續處理
在這裏插入圖片描述
應用狀態是 Flink 中的一等公民,Flink 提供了許多狀態管理相關的特性支持,其中包括

  • 多種狀態基礎類型:Flink
  • 爲多種不同的數據結構提供了相對應的狀態基礎類型,例如原子值(value),列表(list)以及映射(map)。開發者可以基於處理函數對狀態的訪問方式,選擇最高效、最適合的狀態基礎類型。
  • 插件化的State Backend:State Backend 負責管理應用程序狀態,並在需要的時候進行 checkpoint。Flink
    支持多種 state backend,可以將狀態存在內存或者 RocksDB。RocksDB
  • 是一種高效的嵌入式、持久化鍵值存儲引擎。Flink 也支持插件式的自定義 state backend 進行狀態存儲。
  • 精確一次語義:Flink 的 checkpoint 和故障恢復算法保證了故障發生後應用狀態的一致性。因此,Flink
  • 能夠在應用程序發生故障時,對應用程序透明,不造成正確性的影響。 超大數據量狀態:Flink 能夠利用其異步以及增量式的 checkpoint算法,存儲數 TB 級別的應用狀態。 可彈性伸縮的應用:Flink
  • 能夠通過在更多或更少的工作節點上對狀態進行重新分佈,支持有狀態應用的分佈式的橫向伸縮
1.1.2.1.3 時間

時間是流處理應用另一個重要的組成部分。因爲事件總是在特定時間點發生,所以大多數的事件流都擁有事件本身所固有的時間語義。進一步而言,許多常見的流計算都基於時間語義,例如窗口聚合、會話計算、模式檢測和基於時間的 join。流處理的一個重要方面是應用程序如何衡量時間,即區分事件時間(event-time)和處理時間(processing-time)。

Flink 提供了豐富的時間語義支持。

  • 事件時間模式:使用事件時間語義的流處理應用根據事件本身自帶的時間戳進行結果的計算。因此,無論處理的是歷史記錄的事件還是實時的事件,事件時間模式的處理總能保證結果的準確性和一致性。
  • Watermark 支持:Flink 引入了 watermark 的概念,用以衡量事件時間進展。Watermark 也是一種平衡處理延時和完整性的靈活機制。
  • 遲到數據處理:當以帶有 watermark 的事件時間模式處理數據流時,在計算完成之後仍會有相關數據到達。這樣的事件被稱爲遲到事件。Flink
    提供了多種處理遲到數據的選項,例如將這些數據重定向到旁路輸出(side output)或者更新之前完成計算的結果。
  • 處理時間模式:除了事件時間模式,Flink 還支持處理時間語義。處理時間模式根據處理引擎的機器時鐘觸發計算,一般適用於有着嚴格的低延遲需求,並且能夠容忍近似結果的流處理應用

1.1.2.2 分層 API

Flink 根據抽象程度分層,提供了三種不同的 API。每一種 API 在簡潔性和表達力上有着不同的側重,並且針對不同的應用場景。
在這裏插入圖片描述
下文中,我們將簡要描述每一種 API 及其應用,並提供相關的代碼示例

1.1.2.1.4.1 ProcessFunction

ProcessFunction 是 Flink 所提供的最具表達力的接口。ProcessFunction 可以處理一或兩條輸入數據流中的單個事件或者歸入一個特定窗口內的多個事件。它提供了對於時間和狀態的細粒度控制。開發者可以在其中任意地修改狀態,也能夠註冊定時器用以在未來的某一時刻觸發回調函數。因此,你可以利用 ProcessFunction 實現許多有狀態的事件驅動應用所需要的基於單個事件的複雜業務邏輯。

下面的代碼示例展示瞭如何在 KeyedStream 上利用 KeyedProcessFunction 對標記爲 START 和 END 的事件進行處理。當收到 START 事件時,處理函數會記錄其時間戳,並且註冊一個時長4小時的計時器。如果在計時器結束之前收到 END 事件,處理函數會計算其與上一個 START 事件的時間間隔,清空狀態並將計算結果返回。否則,計時器結束,並清空狀態。

/**

 * 將相鄰的 keyed START 和 END 事件相匹配並計算兩者的時間間隔
 * 輸入數據爲 Tuple2<String, String> 類型,第一個字段爲 key 值, 
 * 第二個字段標記 START 和 END 事件。
    */
public static class StartEndDuration
    extends KeyedProcessFunction<String, Tuple2<String, String>, Tuple2<String, Long>> {

  private ValueState<Long> startTime;

  @Override
  public void open(Configuration conf) {
    // obtain state handle
    startTime = getRuntimeContext()
      .getState(new ValueStateDescriptor<Long>("startTime", Long.class));
  }

  /** Called for each processed event. */
  @Override
  public void processElement(
      Tuple2<String, String> in,
      Context ctx,
      Collector<Tuple2<String, Long>> out) throws Exception {

    switch (in.f1) {
      case "START":
        // set the start time if we receive a start event.
        startTime.update(ctx.timestamp());
        // register a timer in four hours from the start event.
        ctx.timerService()
          .registerEventTimeTimer(ctx.timestamp() + 4 * 60 * 60 * 1000);
        break;
      case "END":
        // emit the duration between start and end event
        Long sTime = startTime.value();
        if (sTime != null) {
          out.collect(Tuple2.of(in.f0, ctx.timestamp() - sTime));
          // clear the state
          startTime.clear();
        }
      default:
        // do nothing
    }
  }

  /** Called when a timer fires. */
  @Override
  public void onTimer(
      long timestamp,
      OnTimerContext ctx,
      Collector<Tuple2<String, Long>> out) {

    // Timeout interval exceeded. Cleaning up the state.
    startTime.clear();
  }
}

這個例子充分展現了 KeyedProcessFunction 強大的表達力,也因此是一個實現相當複雜的接口

1.1.2.1.4.2 DataStream API

DataStream API 爲許多通用的流處理操作提供了處理原語。這些操作包括窗口、逐條記錄的轉換操作,在處理事件時進行外部數據庫查詢等。DataStream API 支持 Java 和 Scala 語言,預先定義了例如map()、reduce()、aggregate() 等函數。你可以通過擴展實現預定義接口或使用 Java、Scala 的 lambda 表達式實現自定義的函數。

下面的代碼示例展示瞭如何捕獲會話時間範圍內所有的點擊流事件,並對每一次會話的點擊量進行計數。

// 網站點擊 Click 的數據流
DataStream<Click> clicks = ...

DataStream<Tuple2<String, Long>> result = clicks
  // 將網站點擊映射爲 (userId, 1) 以便計數
  .map(
    // 實現 MapFunction 接口定義函數
    new MapFunction<Click, Tuple2<String, Long>>() {
      @Override
      public Tuple2<String, Long> map(Click click) {
        return Tuple2.of(click.userId, 1L);
      }
    })
  // 以 userId (field 0) 作爲 key
  .keyBy(0)
  // 定義 30 分鐘超時的會話窗口
  .window(EventTimeSessionWindows.withGap(Time.minutes(30L)))
  // 對每個會話窗口的點擊進行計數,使用 lambda 表達式定義 reduce 函數
  .reduce((a, b) -> Tuple2.of(a.f0, a.f1 + b.f1));
1.1.2.1.4.3 SQL & Table API

Flink 支持兩種關係型的 API,Table API 和 SQL。這兩個 API 都是批處理和流處理統一的 API,這意味着在無邊界的實時數據流和有邊界的歷史記錄數據流上,關係型 API 會以相同的語義執行查詢,併產生相同的結果。Table API 和 SQL 藉助了 Apache Calcite 來進行查詢的解析,校驗以及優化。它們可以與 DataStream 和 DataSet API 無縫集成,並支持用戶自定義的標量函數,聚合函數以及表值函數。

Flink 的關係型 API 旨在簡化數據分析、數據流水線和 ETL 應用的定義。

下面的代碼示例展示瞭如何使用 SQL 語句查詢捕獲會話時間範圍內所有的點擊流事件,並對每一次會話的點擊量進行計數。此示例與上述 DataStream API 中的示例有着相同的邏輯。

SELECT userId, COUNT(*)
FROM clicks
GROUP BY SESSION(clicktime, INTERVAL '30' MINUTE), userId

1.1.2.2 庫

Flink 具有數個適用於常見數據處理應用場景的擴展庫。這些庫通常嵌入在 API 中,且並不完全獨立於其它 API。它們也因此可以受益於 API 的所有特性,並與其他庫集成。

複雜事件處理(CEP):模式檢測是事件流處理中的一個非常常見的用例。Flink 的 CEP 庫提供了 API,使用戶能夠以例如正則表達式或狀態機的方式指定事件模式。CEP 庫與 Flink 的 DataStream API 集成,以便在 DataStream 上評估模式。CEP 庫的應用包括網絡入侵檢測,業務流程監控和欺詐檢測。

DataSet API:DataSet API 是 Flink 用於批處理應用程序的核心 API。DataSet API 所提供的基礎算子包括map、reduce、(outer) join、co-group、iterate等。所有算子都有相應的算法和數據結構支持,對內存中的序列化數據進行操作。如果數據大小超過預留內存,則過量數據將存儲到磁盤。Flink 的 DataSet API 的數據處理算法借鑑了傳統數據庫算法的實現,例如混合散列連接(hybrid hash-join)和外部歸併排序(external merge-sort)。

Gelly: Gelly 是一個可擴展的圖形處理和分析庫。Gelly 是在 DataSet API 之上實現的,並與 DataSet API 集成。因此,它能夠受益於其可擴展且健壯的操作符。Gelly 提供了內置算法,如 label propagation、triangle enumeration 和 page rank 算法,也提供了一個簡化自定義圖算法實現的 Graph API。

1.1.3 運維

Apache Flink 是一個針對無界和有界數據流進行有狀態計算的框架。由於許多流應用程序旨在以最短的停機時間連續運行,因此流處理器必須提供出色的故障恢復能力,以及在應用程序運行期間進行監控和維護的工具。

Apache Flink 非常注重流數據處理的可運維性。因此在這一小節中,我們將詳細介紹 Flink 的故障恢復機制,並介紹其管理和監控應用的功能。

1.1.3.1 7 * 24小時穩定運行

在分佈式系統中,服務故障是常有的事,爲了保證服務能夠7*24小時穩定運行,像Flink這樣的流處理器故障恢復機制是必須要有的。顯然這就意味着,它(這類流處理器)不僅要能在服務出現故障時候能夠重啓服務,而且還要當故障發生時,保證能夠持久化服務內部各個組件的當前狀態,只有這樣才能保證在故障恢復時候,服務能夠繼續正常運行,好像故障就沒有發生過一樣。

Flink通過幾下多種機制維護應用可持續運行及其一致性:

  • 檢查點的一致性: Flink的故障恢復機制是通過建立分佈式應用服務狀態一致性檢查點實現的,當有故障產生時,應用服務會重啓後,再重新加載上一次成功備份的狀態檢查點信息。結合可重放的數據源,該特性可保證精確一次(exactly-once)的狀態一致性。
  • 高效的檢查點: 如果一個應用要維護一個TB級的狀態信息,對此應用的狀態建立檢查點服務的資源開銷是很高的,爲了減小因檢查點服務對應用的延遲性(SLAs服務等級協議)的影響,Flink採用異步及增量的方式構建檢查點服務。
  • 端到端的精確一次: Flink 爲某些特定的存儲支持了事務型輸出的功能,及時在發生故障的情況下,也能夠保證精確一次的輸出。
  • 集成多種集羣管理服務: Flink已與多種集羣管理服務緊密集成,如 Hadoop YARN, Mesos, 以及 Kubernetes。當集羣中某個流程任務失敗後,一個新的流程服務會自動啓動並替代它繼續執行。
  • 內置高可用服務: Flink內置了爲解決單點故障問題的高可用性服務模塊,此模塊是基於Apache ZooKeeper 技術實現的,Apache ZooKeeper是一種可靠的、交互式的、分佈式協調服務組件

1.1.3.2 Flink能夠更方便地升級、遷移、暫停、恢復應用服務

驅動關鍵業務服務的流應用是經常需要維護的。比如需要修復系統漏洞,改進功能,或開發新功能。然而升級一個有狀態的流應用並不是簡單的事情,因爲在我們爲了升級一個改進後版本而簡單停止當前流應用並重啓時,我們還不能丟失掉當前流應用的所處於的狀態信息。

而Flink的 Savepoint 服務就是爲解決升級服務過程中記錄流應用狀態信息及其相關難題而產生的一種唯一的、強大的組件。一個 Savepoint,就是一個應用服務狀態的一致性快照,因此其與checkpoint組件的很相似,但是與checkpoint相比,Savepoint 需要手動觸發啓動,而且當流應用服務停止時,它並不會自動刪除。Savepoint 常被應用於啓動一個已含有狀態的流服務,並初始化其(備份時)狀態。Savepoint 有以下特點:

  • 便於升級應用服務版本: Savepoint 常在應用版本升級時使用,當前應用的新版本更新升級時,可以根據上一個版本程序記錄的 Savepoint 內的服務狀態信息來重啓服務。它也可能會使用更早的 Savepoint
    還原點來重啓服務,以便於修復由於有缺陷的程序版本導致的不正確的程序運行結果。
  • 方便集羣服務移植: 通過使用 Savepoint,流服務應用可以自由的在不同集羣中遷移部署。
  • 方便Flink版本升級: 通過使用 Savepoint,可以使應用服務在升級Flink時,更加安全便捷。
  • 增加應用並行服務的擴展性: Savepoint 也常在增加或減少應用服務集羣的並行度時使用。
  • 便於A/B測試及假設分析場景對比結果: 通過把同一應用在使用不同版本的應用程序,基於同一個 Savepoint 還原點啓動服務時,可以測試對比2個或多個版本程序的性能及服務質量。
  • 暫停和恢復服務: 一個應用服務可以在新建一個 Savepoint 後再停止服務,以便於後面任何時間點再根據這個實時刷新的 Savepoint 還原點進行恢復服務。
  • 歸檔服務: Savepoint 還提供還原點的歸檔服務,以便於用戶能夠指定時間點的 Savepoint 的服務數據進行重置應用服務的狀態,進行恢復服務。

1.1.3.3 監控和控制應用服務

如其它應用服務一樣,持續運行的流應用服務也需要監控及集成到一些基礎設施資源管理服務中,例如一個組件的監控服務及日誌服務等。監控服務有助於預測問題並提前做出反應,日誌服務提供日誌記錄能夠幫助追蹤、調查、分析故障發生的根本原因。最後,便捷易用的訪問控制應用服務運行的接口也是Flink的一個重要的亮點特徵。

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還提供元數據信息和已採集的運行中或完成後的應用服務的指標信息。

1.2 應用場景

  • Apache Flink 功能強大,支持開發和運行多種不同種類的應用程序。
  • 它的主要特性包括:批流一體化、精密的狀態管理、事件時間支持以及精確一次的狀態一致性保障等。Flink 不僅可以運行在包括 YARN、 Mesos、Kubernetes 在內的多種資源管理框架上,還支持在裸機集羣上獨立部署。在啓用高可用選項的情況下,它不存在單點失效問題。
  • 事實證明,Flink 已經可以擴展到數千核心,其狀態可以達到 TB 級別,且仍能保持高吞吐、低延遲的特性。世界各地有很多要求嚴苛的流處理應用都運行在 Flink 之上.

1.2.1 事件驅動型應用

  • 事件驅動型應用是一類具有狀態的應用,它從一個或多個事件流提取數據,並根據到來的事件觸發計算、狀態更新或其他外部動作。
  • 事件驅動型應用是在計算存儲分離的傳統應用基礎上進化而來。在傳統架構中,應用需要讀寫遠程事務型數據庫。
  • 相反,事件驅動型應用是基於狀態化流處理來完成。在該設計中,數據和計算不會分離,應用只需訪問本地(內存或磁盤)即可獲取數據。系統容錯性的實現依賴於定期向遠程持久化存儲寫入 checkpoint。

下圖描述了傳統應用和事件驅動型應用架構的區別。
在這裏插入圖片描述

1.2.1.1 事件驅動型應用的優勢?

事件驅動型應用無須查詢遠程數據庫,本地數據訪問使得它具有更高的吞吐和更低的延遲。而由於定期向遠程持久化存儲的 checkpoint工作可以異步、增量式完成,因此對於正常事件處理的影響甚微。事件驅動型應用的優勢不僅限於本地數據訪問。傳統分層架構下,通常多個應用會共享同一個數據庫,因而任何對數據庫自身的更改(例如:由應用更新或服務擴容導致數據佈局發生改變)都需要謹慎協調。反觀事件驅動型應用,由於只需考慮自身數據,因此在更改數據表示或服務擴容時所需的協調工作將大大減少。

1.2.1.2 Flink 如何支持事件驅動型應用?

事件驅動型應用會受制於底層流處理系統對時間和狀態的把控能力,Flink 諸多優秀特質都是圍繞這些方面來設計的。它提供了一系列豐富的狀態操作原語,允許以精確一次的一致性語義合併海量規模(TB 級別)的狀態數據。此外,Flink 還支持事件時間和自由度極高的定製化窗口邏輯,而且它內置的 ProcessFunction 支持細粒度時間控制,方便實現一些高級業務邏輯。同時,Flink 還擁有一個複雜事件處理(CEP)類庫,可以用來檢測數據流中的模式。

Flink 中針對事件驅動應用的明星特性當屬 savepoint。Savepoint 是一個一致性的狀態映像,它可以用來初始化任意狀態兼容的應用。在完成一次 savepoint 後,即可放心對應用升級或擴容,還可以啓動多個版本的應用來完成 A/B 測試。

1.2.1.3 典型的事件驅動型應用實例

  • 反欺詐
  • 異常檢測
  • 基於規則的報警
  • 業務流程監控
  • (社交網絡)Web 應用

1.2.2 數據分析應用

1.2.2.1 什麼是數據分析應用?

數據分析任務需要從原始數據中提取有價值的信息和指標。傳統的分析方式通常是利用批查詢,或將事件記錄下來並基於此有限數據集構建應用來完成。爲了得到最新數據的分析結果,必須先將它們加入分析數據集並重新執行查詢或運行應用,隨後將結果寫入存儲系統或生成報告。

藉助一些先進的流處理引擎,還可以實時地進行數據分析。和傳統模式下讀取有限數據集不同,流式查詢或應用會接入實時事件流,並隨着事件消費持續產生和更新結果。這些結果數據可能會寫入外部數據庫系統或以內部狀態的形式維護。儀表展示應用可以相應地從外部數據庫讀取數據或直接查詢應用的內部狀態。

如下圖所示,Apache Flink 同時支持流式及批量分析應用。
在這裏插入圖片描述

1.2.2.2 流式分析應用的優勢?

和批量分析相比,由於流式分析省掉了週期性的數據導入和查詢過程,因此從事件中獲取指標的延遲更低。不僅如此,批量查詢必須處理那些由定期導入和輸入有界性導致的人工數據邊界,而流式查詢則無須考慮該問題。

另一方面,流式分析會簡化應用抽象。批量查詢的流水線通常由多個獨立部件組成,需要週期性地調度提取數據和執行查詢。如此複雜的流水線操作起來並不容易,一旦某個組件出錯將會影響流水線的後續步驟。而流式分析應用整體運行在 Flink 之類的高端流處理系統之上,涵蓋了從數據接入到連續結果計算的所有步驟,因此可以依賴底層引擎提供的故障恢復機制。

1.2.2.3 Flink 如何支持數據分析類應用?

Flink 爲持續流式分析和批量分析都提供了良好的支持。具體而言,它內置了一個符合 ANSI 標準的 SQL 接口,將批、流查詢的語義統一起來。無論是在記錄事件的靜態數據集上還是實時事件流上,相同 SQL 查詢都會得到一致的結果。同時 Flink 還支持豐富的用戶自定義函數,允許在 SQL 中執行定製化代碼。如果還需進一步定製邏輯,可以利用 Flink DataStream API 和 DataSet API 進行更低層次的控制。此外,Flink 的 Gelly 庫爲基於批量數據集的大規模高性能圖分析提供了算法和構建模塊支持。

1.2.2.4 典型的數據分析應用實例

  • 電信網絡質量監控
  • 移動應用中的產品更新及實驗評估分析
  • 消費者技術中的實時數據即席分析
  • 大規模圖分析

1.2.3 數據管道應用

1.2.3.1 什麼是數據管道?

提取-轉換-加載(ETL)是一種在存儲系統之間進行數據轉換和遷移的常用方法。ETL 作業通常會週期性地觸發,將數據從事務型數據庫拷貝到分析型數據庫或數據倉庫。

數據管道和 ETL 作業的用途相似,都可以轉換、豐富數據,並將其從某個存儲系統移動到另一個。但數據管道是以持續流模式運行,而非週期性觸發。因此它支持從一個不斷生成數據的源頭讀取記錄,並將它們以低延遲移動到終點。例如:數據管道可以用來監控文件系統目錄中的新文件,並將其數據寫入事件日誌;另一個應用可能會將事件流物化到數據庫或增量構建和優化查詢索引。

下圖描述了週期性 ETL 作業和持續數據管道的差異。
在這裏插入圖片描述

1.2.3.2 數據管道的優勢?

和週期性 ETL 作業相比,持續數據管道可以明顯降低將數據移動到目的端的延遲。此外,由於它能夠持續消費和發送數據,因此用途更廣,支持用例更多。

1.2.3.3 Flink 如何支持數據管道應用?

很多常見的數據轉換和增強操作可以利用 Flink 的 SQL 接口(或 Table
API)及用戶自定義函數解決。如果數據管道有更高級的需求,可以選擇更通用的 DataStream API 來實現。Flink
爲多種數據存儲系統(如:Kafka、Kinesis、Elasticsearch、JDBC數據庫系統等)內置了連接器。同時它還提供了文件系統的連續型數據源及數據匯,可用來監控目錄變化和以時間分區的方式寫入文件

1.2.3.4 典型的數據管道應用實例

  • 電子商務中的實時查詢索引構建
  • 電子商務中的持續 ETL

1.3 Apache Flink 用戶

Apache Flink 爲全球許多公司和企業的關鍵業務提供支持。在這個頁面上,我們展示了一些著名的 Flink 用戶,他們在生產中運行着有意思的用例,並提供了展示更詳細信息的鏈接。

在項目的 wiki 頁面中有一個 誰在使用 Flink 的頁面,展示了更多的 Flink 用戶。請注意,該列表並不全面。我們只添加明確要求列出的用戶。

如果你希望加入此頁面,請通過 Flink 用戶郵件列表告訴我們

在這裏插入圖片描述
點擊查看更多

1.4 總結

在這裏插入圖片描述
本篇完~

下篇:跟着官網學 Apache Flink 1.10.0 之實戰篇

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章