0


一文搞懂大数据流式计算引擎Flink【万字详解,史上最全】

往期推荐

一文入门大数据准流式计算引擎Spark【万字详解,全网最新】-CSDN博客

浅谈维度建模、数据分析模型,何为数据仓库,与数据库的区别_统一数仓 数据库用户名-CSDN博客数仓架构:离线数仓、实时数仓Lambda和Kappa、湖仓一体数据湖-CSDN博客

数仓分层ODS、DWD、DWM、DWS、DIM、DM、ADS_ods dwd dws ads dm-CSDN博客浅谈维度建模、数据分析模型,何为数据仓库,与数据库的区别_统一数仓 数据库用户名-CSDN博客

0. Flink知识图谱

1. Flink发展

Apache Flink 诞生于柏林工业大学的一个研究性项目,原名 StratoSphere 。2014 年,由 StratoSphere 项目孵化出 Flink,并于同年捐赠 Apache,之后成为 Apache 的顶级项目。2019 年 1 年,阿里巴巴收购了 Flink 的母公司 Data Artisans,并宣布开源内部的 Blink,Blink 是阿里巴巴基于 Flink 优化后的版本,增加了大量的新功能,并在性能和稳定性上进行了各种优化,经历过阿里内部多种复杂业务的挑战和检验。同时阿里巴巴也表示会逐步将这些新功能和特性 Merge 回社区版本的 Flink 中,因此 Flink 成为目前最为火热的大数据处理框架。

1.1 四代计算引擎

在国外一些社区,有很多人将大数据的计算引擎分成了 4 代,当然,也有很多人不会认同。我们先姑且这么认为和讨论。

  • 首先第一代的计算引擎,无疑就是 Hadoop 承载的 MapReduce。这里大家应该都 不会对 MapReduce 陌生,它将计算分为两个阶段,分别为 Map 和 Reduce。对于上层应用来说,就不得不想方设法去拆分算法,甚至于不得不在上层应用实现 多个 Job 的串联,以完成一个完整的算法,例如迭代计算。 由于这样的弊端,催生了支持 DAG 框架的产生
  • 因此,支持 DAG 的框架被划分为第二代计算引擎。如 Tez 以及更上层的 Oozie。这里我们不去细究各种 DAG 实现之间的区别,不过对于当时的 Tez 和 Oozie 来说,大多还是批处理的任务
  • 接下来就是以 Spark 为代表的第三代的计算引擎。第三代计算引擎的特点主要 是 Job 内部的 DAG 支持(不跨越 Job),以及强调的准实时计算。在这里,很多人也会认为第三代计算引擎也能够很好的运行批处理的 Job。 随着第三代计算引擎的出现,促进了上层应用快速发展,例如各种迭代计算的性能以及对流计算和 SQL 等的支持。
  • Flink 的诞生就被归在了第四代。这应该主 要表现在 Flink 对流计算的支持,以及更一步的实时性上面。当然 Flink 也可 以支持 Batch 的任务,以及 DAG 的运算。

2. Flink简介

  • Flink 是一个分布式、高性能、有状态的流处理框架,它能够对有界和无界的数据流进行高效的处理。Flink 的 核心是流处理(DataStream),当然也支持批处理(DataSet),Flink 将批处理看成是流处理的一种特殊情况,即数据流是有 明确界限的。这和 Spark Streaming 的思想是完全相反的,Spark Streaming 的核心是批处理,它将流处理看成是批处理的一种特殊情况, 即把数据流进行极小粒度的拆分,拆分为多个微批处理。

2.1 Flink特点

  • 支持高吞吐、低延迟、高性能的流处理
  • 结果准确,Flink提供了事件时间和处理时间,对乱序数据仍能提供一直准确的结果
  • 支持高度灵活的窗口(Window)操作,支持基于 time、count、session, 以及 data-driven 的窗口操作
  • 支持基于轻量级分布式快照(Snapshot)实现的容错
  • 一个运行时同时支持 Batch on Streaming 处理和 Streaming 处理
  • Flink 在 JVM 内部实现了自己的内存管理
  • 支持迭代计算,Spark也支持
  • 支持程序自动优化:避免特定情况下 Shuffle、排序等昂贵操作,中间结果有必要进行缓存

2.2 批处理和流处理

  • 批处理 有界、持久、大量,一般用于离线计算
  • 流处理 无界、实时,流处理方式无需对整个数据集执行操作,而是对通过系统传输的每个数据项执行操作,一般用于实时统计

在 Spark 生态体系中,对于批处理和流处理采用了不同的技术框架,批处理由 SparkSQL 实现,流处理由 Spark Streaming 实现,这也是大部分框架采用的策略,使用独立的处理器实现批处理和流处理,而 Flink 可以同时实现批处理和流处理,Flink 将批处理(即处理 有限的静态数据)视作一种特殊的流处理,即把数据看作是有界的 !

2.3 有界流和无界流

无界数据流:

  • 有定义流的开始,但没有定义流的结束
  • 它们会无休止的产生数据
  • 无界流的数据必须持续处理,即数据被摄取后需要立刻处理
  • 我们不能等到所有数据都到达再处理,因为输入是无限的。

有界数据流:

  • 有定义流的开始,也有定义流的结束
  • 有界流可以在摄取所有数据后再进行计算
  • 有界流所有数据可以被排序,所以并不需要有序摄取
  • 有界流处理通常被称为批处理。

2.4 Flink和Spark Streaming

Spark本质是批处理

  • Spark数据模型:Spak采用RDD模型,Spark Streaming的DStream实际上也就是一组组小批据RDD的集合
  • Spark运行时架构:Spark是批计算,将DAG划分为不同的stage,一个完成后才可以计算下一个

Flink以流处理为根本

  • Flink数据模型:Flink基本据模型是数据流,以及事件(Event)序列
  • Flink运行时架构:Flink是标准的流执行模式,一个事件在一个节点处理完后可以直接发往下一个节点进行处理

3. Flink三层核心架构

下图为 Flink 技术栈的核心组成部分,由上而下分别是 API & Libraries 层、Runtime 核心层以及物理部署层。

  • *API & Libraries 层,*提供了面向流式处理的接口(DataStream API)、面向批处理的接口(DataSet API)、用于复杂事件处理的 CEP 库、用于结构化数据查询的 SQL & Table 库、基于批处理的机器学习库 FlinkML 和 图形处理库 Gelly
  • Runtime 核心层,这一层是 Flink 分布式计算框架的核心实现层,包括作业转换,任务调度,资源分配,任务执行等功能,基于这一层的实现,可以在流式引擎下同时进行流处理和批处理。
  • 物理部署层,用于支持在不同平台上部署运行 Flink 应用。

3.1 API & Libraries层详解

在API & Libraries层,有如下更细致的划分,API 的一致性由下至上依次递增,接口的表现能力由下至上依次递减。

3.1.1 SQL&Table API层

SQL & Table API 同时适用于批处理和流处理,这意味着可以对有界数据流和无界数据流以相同的语义进行查询,并产生相同的结果。除了基本查询外, 它还支持自定义的标量函数,聚合函数以及表值函数,可以满足多样化的查询需求。

3.1.2 DataStream & DataSet API层

DataStream & DataSet API 是 Flink 数据处理的核心 API,支持使用 Java 语言或 Scala 语言进行调用,提供了数据读取,数据转换和数据输出等一系列常用操作的封装。

3.1.3 Stateful Stream Processing层

Stateful Stream Processing 是最低级别的抽象,它通过 Process Function 函数内嵌到 DataStream API 中。 Process Function 是 Flink 提供的最底层 API,具有最大的灵活性,允许开发者对时间和状态进行细粒度的控制

4. 三种Time概念

在 Flink 中,如果以时间段划分边界的话,那么时间就是一个极其重要的字段。 Flink 中的时间有三种类型,如下图所示:

  • Event Time:是事件创建的时间。它通常由事件中的时间戳描述,即事件本身就要携带时间信息,例如采集的日志数据中,每一条日志都会记录自己的生成时间,Flink 通过时间戳分配器访问事件时间戳。
  • Ingestion Time:是数据进入 Flink 的时间。
  • Processing Time:是每一个执行基于时间操作的算子的本地系统时间,与机器相关,默认的时间属性就是 Processing Time

在 Flink 的流式处理中,绝大部分的业务都会使用 eventTime,一般只在 eventTime 无法使用时,才会被迫使用 ProcessingTime

4.1 WaterMark水印

  • 流处理从事件产生,到流经 source,再到 operator,中间有一个过程和时间,虽然大部分情况下,流到 operator 的数据都是按照事件产生的 时间顺序来的,但是也不排除由于网络、背压等原因,导致乱序的产生,所谓乱序,就是指 Flink 接收到的事件的先后顺序不是严格按照事件的 Event Time 顺序排列的,所以 Flink 最初设计的时候,就考虑到了网络延迟,网络乱序等问题,所以提出了一个抽象概念:水印(WaterMark)
  • 当出现乱序,如果只根据 EventTime 决定 Window 的运行,我们不能明确数据是否全部到位,但又不能无限期的等下去, 此时必须要有个机制来保证一个特定的时间后,必须触发 Window 去进行计算了, 这个特别的机制,就是 Watermark。
  • Watermark 是用于处理乱序事件的,通常用 Watermark 机制结合 Window 来实现。 数据流中的 Watermark 用于表示 timestamp 小于 Watermark 的数据,都已经到达了,因此,Window 的执行也是由 Watermark 触发的。 Watermark 可以理解成一个延迟触发机制,我们可以设置 Watermark 的延时时长 t ,每次系统会校验已经到达的数据中最大的 maxEventTime,然后认定 EventTime 小于 maxEventTime - t 的所有数据都已经到达,如果有窗口的停止时间等于 maxEventTime - t,那么这个窗口被触发执行。

对延迟数据的理解

  • 延迟数据是指: 在当前窗口【假设窗口范围为 10-15】已经计算之后,又来了一个属于该窗口的 数据【假设事件时间为 13】,这时候仍会触发 Window 操作,这种数据就称为 延迟数据。
  • 那么问题来了,延迟时间怎么计算呢? 假设窗口范围为 10-15,延迟时间为 2s,则只要 WaterMark=15+2, 10-15 这个窗口就不能再触发 Window 操作,即使新来的数据的 Event Time 属 于这个窗口时间内 。

5. Windows窗口类型

在大多数场景下,我们需要统计的数据流都是无界的,因此我们无法等待整个数据流终止后才进行统 计。通常情况下,我们只需要对某个时间范围或者数量范围内的数据进行统计分析(把无限数据分割成块进行计算分析):如每隔五分钟统计一次过去一小时内所有商品的点击量;或者每发生1000次点击后,都去统计一下每个商品点击率的占比。在 Flink 中,可以使用窗口 (Window) 来实现这类功能。按照统计维度的不同,Flink 中的窗口可以分为时间窗口 (Time Windows) 和计数窗口 (Count Windows) 。

5.1 时间窗口

时间窗口以时间点来定义窗口的开始(start)和结束(end),所以截取出的就是某一时间段的数据。到达结束时间时,窗口不再收集数据,触发计算输出结果,并将窗口关闭销毁。所以可以说基本思路就是“定点发车”。

5.1.1 滚动窗口Tumbling Windows

滚动窗口指彼此之间没有重叠的窗口。例如:每隔1小时统计过去1小时内的商品点击量,那么 1 天就只能分为 24 个窗口,每个窗口之间是不存在重叠的。

特点:时间对齐,长度固定,窗口不重叠

5.1.2 滑动窗口Sliding Windows

滑动窗口用于滚动进行聚合分析,例如:每隔 6 分钟统计一次过去一小时内所有商品的点击量,那么1天可以分为 240 个窗口,统计窗口之间存在重叠。

特点:时间对齐,长度固定,窗口重叠

5.1.3 会话窗口Session Windows

当用户在进行持续浏览时,可能每时每刻都会有点击数据,例如在活动区间内,用户可能频繁的将某类 商品加入和移除购物车,而你只想知道用户本次浏览最终的购物车情况,此时就等用户持有的会话结束后再进行统计。想要实现这类统计,可以通过 Session Windows 来进行实现。

特点:时间不对齐,长度不固定,窗口不重叠

5.1.4 全局窗口Global Windows

全局窗口会将所有** key 相同的元素分配到同一个窗口**中,其通常配合触发器 (trigger) 进行使用。如果没有相应触发器,则计算将不会被执行。

5.2 计数窗口

计数窗口基于元素的个数来截取数据,到达固定的个数时就触发计算并关闭窗口。每个窗口截取数据的个数, 就是窗口的大小。基本思路是“人齐发车”。

Count Windows 用于以数量为维度来进行数据聚合,同样也分为滚动窗口和滑动窗口,实现方式也和 时间窗口基本一致。

注意:CountWindow 的 window_size 指的是相同 Key 的元素的个数,不是输入的所有元素的总数

  • tumbling-count-window (无重叠数据)
  • sliding-count-window (有重叠数据)

6. 状态管理

参考博客:Flink 状态管理详解(超全收藏)_flink状态后端的应用场景-CSDN博客

6.1 状态的Flink官方定义

当前计算流程需要依赖到之前计算的结果,那么之前计算的结果就是状态。

6.2 状态分类及状态存储类型

相对于其他流计算框架,Flink 一个比较重要的特性就是其支持有状态计算,即你可以将中间的计算结果进行保存,并提供给后续的计算使用(Spark的RDD也可以保存计算结果供下个RDD使用,DAG)
具体而言,Flink 有两种基本类型的状态 (State) : 键控状态(Keyed State) 与算子状态(Operator State)。
这两种状态可以以两种形式存在:原始状态(raw state) 、托管状态(managed state),托管状态是由 Flink 框架管理的状态,原始状态由用户自行管理状态。

6.2.1 算子状态

算子状态是和算子进行绑定的,与Key无关,一个算子的状态不能被其他算子所访问到。官方文档上对 Operator State 的解释是:each operator state is bound to one parallel operator instance,所以更为确切的说一个算子状态是与一个并发的算子实例所绑定的,即假设算子的并行度是 2,那么其应有两个对应的算子状态:

算子状态存储类型

  • ListState:存储列表类型的状态。
  • UnionListState:存储列表类型的状态,与 ListState 的区别在于:如果并行度发生变化, ListState 会将该算子的所有并发的状态实例进行汇总,然后均分给新的 Task;而 UnionListState 只是将所有并发的状态实例汇总起来,具体的划分行为则由用户进行定义。
  • BroadcastState:用于广播的算子状态。

6.2.2 键控状态

键控状态是一种特殊的算子状态,即状态是根据 key 值进行区分的,Flink 会为每类键值维护一个状态实例。如下图所示,每个颜色代表不同 key 值,对应四个不同的状态实例。需要注意的 是键控状态只能在 KeyedStream 上进行使用,我们可以通过 stream.keyBy(...) 来得到 KeyedStream 。

键控状态存储类型

  • ValueState:存储单值类型的状态。可以使用 update(T) 进行更新,并通过 T value() 进行 检索。
  • ListState:存储列表类型的状态。可以使用 add(T) 或 addAll(List) 添加元素;并通过 get() 获得整个列表。
  • ReducingState:用于存储经过 ReduceFunction 计算后的结果,使用 add(T) 增加元素。 AggregatingState:用于存储经过 AggregatingState 计算后的结果,使用 add(IN) 添加元素。
  • FoldingState:已被标识为废弃,会在未来版本中移除,官方推荐使用 AggregatingState 代 替。
  • MapState:维护 Map 类型的状态。

6.2.3 Broadcast State

Broadcast State 是 Flink 1.5 引入的新特性。在开发过程中,如果遇到需要 下发/广播配置、规则等低吞吐事件流到下游所有 task 时,就可以使用 Broadcast State 特性。下游的 task 接收这些配置、规则并保存为 BroadcastState, 将这些配置应用到另一个数据流的计算中 。

6.3. 状态后端(持久化存储)

默认情况下,所有的状态都存储在 JVM 的堆内存中,在状态数据过多的情况下,这种方式很有可能导致内存溢出,因此 Flink 该提供了其它方式来存储状态数据,这些存储方式统一称为状态后端 (或状态管理器),主要有以下三种:

  • MemoryStateBackend 默认的方式,即基于 JVM 的堆内存进行存储,主要适用于本地开发和调试。
  • FsStateBackend****基于文件系统进行存储,可以是本地文件系统,也可以是 HDFS 等分布式文件系统。 需要注意而是虽然选择使用了 FsStateBackend ,但正在进行的数据仍然是存储在 TaskManager 的内存中的,只有在 checkpoint 时,才会将状态快照写入到指定文件系统上。
  • RocksDBStateBackend RocksDBStateBackend 是 Flink 内置的第三方状态管理器,采用嵌入式的 key-value 型数据库 RocksDB 来存储正在进行的数据。等到 checkpoint 时,再将其中的数据持久化到指定的文件系统中, 所以采用 RocksDBStateBackend 时也需要配置持久化存储的文件系统。之所以这样做是因为 RocksDB 作为嵌入式数据库安全性比较低,但比起全文件系统的方式,其读取速率更快;比起全内存的方式,其 存储空间更大,因此它是一种比较均衡的方案。

7. Flink算子

7.1 DataSet批处理算子

7.1.1 Source算子

  • fromCollection:从本地集合读取数据
  • readTextFile:从文件中读取
  • readTextFile:遍历目录
  • readTextFile:读取压缩文件

7.1.2 Transform 转换算子

Transform 算子基于 Source 算子操作,所以要首先构建 Flink 执行环境及 Source 算子。

数据源读入数据之后,就可以使用各种转换算子,将一个或多个 DataStream 转换为新的 DataStream。

基本转换算子(map/ filter/ flatMap

  • map:将 DataSet 中的每一个元素转换为另外一个元素
  • flatMap:将 DataSet 中的每一个元素转换为 0...n 个元素
  • filter:过滤出来一些符合条件的元素,返回 boolean 值为 true 的元素

聚合算子(Aggregation

  • reduce:可以对一个 dataset 或者一个 group 来进行聚合计算,最终聚合成一个元素reduceGroup:将一个 dataset 或者一个 group 聚合成一个或多个元素。reduceGroup 是 reduce 的一种优化方案; 它会先分组 reduce,然后在做整体的 reduce;这样做的好处就是可以减少网络 IO
  • minBy 和 maxBy:选择具有最小值或最大值的元素
  • Aggregate:在数据集上进行聚合求最值(最大值、最小值),注意: 使用 aggregate,只能使用字段索引名或索引名称来进行分组 groupBy(0) ,否则会报一下错误: Exception in thread "main" java.lang.UnsupportedOperationException: Aggregate does not support grouping with KeySelector functions, yet.
  • .........

7.1.3 Sink 输出算子

Flink 作为数据处理框架,最终还是要把计算处理的结果写入外部存储,为外部应用提供 支持。

  • collect 将数据输出到本地集合
  • writeAsText 将数据输出到文件

7.2 DataStream流处理算子

流处理算子和批处理算子差不多,就不详细解释了。

参考博客:一文学完Flink流计算常用算子(Flink算子大全)_flink算子scala-CSDN博客

8. Flink容错

8.1 Checkpoint机制

Flink 的 checkpoint 机制原理来自“Chandy-Lamport algorithm”算法

为了使状态具有良好的容错性,Flink 提供了检查点机制 (CheckPoints) 。通过检查点机制, Flink 定期在数据流上生成 checkpoint barrier ,当某个算子收到 barrier 时,即会基于当前状态生成一份快照,然后再将该 barrier 传递到下游算子,下游算子接收到该 barrier 后,也基于当前状态生成一份快照,依次传递直至到最后的 Sink 算子上。当出现异常后,Flink 就可以根据最近的一次的快照数据将所有算子恢复到先前的状态。(Spark也有Checkpoint机制)

简单理解为 checkpoint 是把 state 数据定时持久化存储了

9. Flink CEP

Complex Event Processing,复杂事件处理,Flink CEP 是一个基于 Flink 的复杂事件处理库,可以从多个数据流中发现复杂事件,识别有意义的事件(例如机会或者威胁),并尽快的做出响应,而不是需要等待几天或则几个月相当长的时间,才发现问题。

9.1 使用场景

检测恶意用户和刷屏用户

实时反作弊和风控

实时营销

实时网络攻击检测

9.2 CEP API

CEP API 的核心是 Pattern(模式) API,它允许你快速定义复杂的事件模式。每 个模式包含多个阶段(stage)或者也可称为状态(state)。从一个状态切换到另一个状态,用户可以指定条件,这些条件可以作用在邻近的事件或独立事件上。

10. Flink CDC

  • CDC 是 Change Data Capture(变更数据获取)的简称。核心思想是,监测并捕获数据库的变动(包括数据或数据表的插入、更新以及删除等,和Flume很像,不过Flume是监控的系统日志),将这些变更按发生的顺序完整记录下来,写入到消息中间件中以供其他服务进行订阅及消费
  • 在广义的概念上,只要能捕获数据变更的技术,我们都可以称为 CDC 。通常我们说的 CDC 技术主要面向数据库的变更,是一种用于捕获数据库中数据变更的技术。
  • CDC 技术应用场景非常广泛: 数据同步,用于备份,容灾; 数据分发,一个数据源分发给多个下游; 数据采集(E),面向数据仓库/数据湖的 ETL 数据集成

10.1 CDC种类

CDC 主要分为基于查询和基于 Binlog 两种方式,我们主要了解一下这两种之间的区别:

11. Flink SQL

  • Flink SQL 是 Flink 实时计算为简化计算模型,降低用户使用实时计算门槛而设计的一套符合标准 SQL 语义的开发语言(为了降低Spark门槛,也有Spark SQL;为了降低HBase门槛,有了Phoneix;为了方便的操作HDFS文件,有了Hive SQL......)。 自 2015 年开始,阿里巴巴开始调 研开源流计算引擎,最终决定基于 Flink 打造新一代计算引擎,针对 Flink 存在的不足进行优化和改进,并且在 2019 年初将最终代码开源,也就是我们熟知 的 Blink。Blink 在原来的 Flink 基础上最显著的一个贡献就是 Flink SQL 的 实现。
  • Flink SQL 是面向用户的 API 层,在我们传统的流式计算领域,比如 Storm、 Spark Streaming 都会提供一些 Function 或者 Datastream API,用户通过 Java 或 Scala 写业务逻辑,这种方式虽然灵活,但有一些不足,比如具备一定门槛且调优较难,随着版本的不断更新,API 也出现了很多不兼容的地方。在这个背景下,毫无疑问,SQL 就成了我们最佳选择!

本文转载自: https://blog.csdn.net/qq_73181349/article/details/141899842
版权归原作者 青秋. 所有, 如有侵权,请联系我们删除。

“一文搞懂大数据流式计算引擎Flink【万字详解,史上最全】”的评论:

还没有评论