1. 简介
Flink 核心是一个流式的数据流执行引擎,其针对数据流的分布式计算提供了数据分布、数据通信以及容错机制等功能。基于流执行引擎,Flink 提供了诸多更高抽象层的 API 以便用户编写分布式任务
1.1.无界数据流与有界数据流
1.1.1.无界数据流
无界数据流有一个开始但是没有结束 , 它们不会在生成时终止并 提供数据,必须连续处理无界流,也就是说必须在获取后立即 处理 event 。对于无界 数据流我们无法等待所有数据都到达, 因为输入是无界的, 并且在任何时间点都不 会完成。处理无界数据通常要求以特定顺序(例如事件发生的顺序)获取 event ,以 便能够推断结果完整性 ,无界流的处理称为流处理 。
1.1.2.有界数据流
有界数据流有明确定义的开始和结束, 可以在执行任何计算之前 通过获取所有数据来处理有界流, 处理有界流不需要有序获取, 因为可以始终对有 界数据集进行排序, 有界流的处理也称为批处理。
1.2.批处理和流处理
批处理的特点是有界、持久、大量, 批处理非常适合需要访问全套记录才能完成的计算工作, 一般用于离线统计。
流处理的特点是无界、实时, 流处理方式无需针对整个数据集执行操作, 而是对通过系统传输的每个数据项执行操作 , 一般用于实时统计 。
1.3.Flink 批流一体处理
在 Spark 生态体系中, 对于批处理和流处理采用了不同的技术框架,批处理由 Spark SQL 实现, 流处理由 Spark Streaming 实现, 这也是大部分框架采用的策略, 使用独立的处理器实现批处理和流处理, 而 Flink 可以同时实现批处理和流处理。
Apache Flink 是一个面向分布式数据流处理和批量数据处理的开源计算平台,能够基于同一个 Flink 运行时 (Flink Runtime) , 提供支持流处理和批处理两种类 型应用的功能 。 现有的开源计算 方案, 会把流处理和批处理作为两种不同的应用类 型,因为它们要实现的目标是完全不相同的:流处理一般需要支持低延迟、 Exactly-once 保证 , 而 批处理需要支持高吞吐、高效处理 , 所以在实现的时候通常 是分别给出两套实现方法, 或者通过一个独立的开源框架来实现其中每一种处理方 案。
Flink 是完全支持流处理,作为流处理时将输入数据流视为无界数据流 ; 批处理被作为一种特殊的流处理, 只是它的输入数据流被定义为有界的 。
1.4.Flink & Spark Streaming
Flink 是标准的实时流处理引擎,基于事件驱动。而 Spark Streaming 是微批[Micro-Batch的模型。
1.4.1.任务调度
Spark Streaming 连续不断的生成微小的数据批次,构建有向无环图 DAG,Spark Streaming 会依次创建 DStreamGraph、JobGenerator、JobScheduler。
Flink 根据用户提交的代码生成 StreamGraph,经过优化生成 JobGraph,然后提交给 JobManager进行处理,JobManager 会根据 JobGraph 生成 ExecutionGraph,ExecutionGraph 是 Flink 调度最核心的数据结构,JobManager 根据 ExecutionGraph 对 Job 进行调度。
1.4.2. 时间机制
Spark Streaming 支持的时间机制有限,只支持处理时间。
Flink 支持了流处理程序在时间上的三个定义:处理时间、事件时间、注入时间。同时也支持 watermark 机制来处理滞后数据。
1.4.3. 容错机制
对于 Spark Streaming 任务,我们可以设置 checkpoint,然后假如发生故障并重启,我们可以从上次 checkpoint 之处恢复,但是这个行为只能使得数据不丢失,可能会重复处理,不能做到恰一次处理语义。
2.系统架构
当 Flink 集群启动后,首先会启动一个JobManger 和一个或多个的 TaskManager。由 Client 提交任务给 JobManager,JobManager 再调度任务到各个 TaskManager 去执行, TaskManager 将心跳和统计信息汇报给 JobManager。
Client
Client 为提交 Job 的客户端,可以是运行在任何机器上[与 JobManager 环境连通即可]。提交 Job 后,Client 可以结束进程,也可以不结束并等待结果返回。
Dispatcher
提供 REST 接口来接收 client 的 application 提交,它负责启动 TaskManager 和提交 application,同时运行 Web UI。
JobManager
JobManager 负责整个 Flink 集群任务的调度以及资源的管理,从客户端中获取提交的 Flink Job,然后根据集群中 TaskManager 上 TaskSlot 的使用情况,为提交的Job 分配相应的 TaskSlot 资源并命令 TaskManager 启动从客户端中获取的应用。
JobManager 相当于整个集群的 Master 节点,且整个集群有且只有一个活跃的 JobManager ,负责整个集群的任务调度和资源管理。
JobManager包含了3个重要的组件
Actor
JobManager 和 TaskManager 之间通过 Actor System 进行通信,获取任务执行的情况并通过 Actor System 将应用的任务执行情况发送给客户端。
调度
检查点
Flink的检查点机制是保证其一致性容错功能的骨架。它持续的为分布式的数据流和有状态的operator生成一致性的快照。Flink的容错机制持续的构建轻量级的分布式快照,因此负载非常低。通常这些有状态的快照都被放在HDFS中存储(state backend)。程序一旦失败,Flink将停止executor并从最近的完成了的检查点开始恢复(依赖可重发的数据源+快照)
TaskManager
TaskManager 相当于整个集群的 Slave 节点,负责具体的任务执行和对应任务在每个节点上的资源申请和管理。
客户端通过将编写好的 Flink 应用编译打包,提交到 JobManager,然后 JobManager 会根据已注册在 JobManager 中 TaskManager 的资源情况,将任务分配给有资源的 TaskManager节点,然后启动并运行任务。
TaskManager 从 JobManager 接收 Job然后使用 Slot 资源启动 Task,建立数据接入的网络连接,接收数据并开始数据处理。同时 TaskManager 之间的数据交互都是通过数据流的方式进行的。
可以看出,Flink 的任务运行其实是采用多线程的方式,这和 MapReduce 多 进程的方式有很大的区别,Flink 能够极大提高 CPU 使用效率,在多个任务和 Task之间通过 TaskSlot 方式共享系统资源,每个 TaskManager 中通过管理多个 TaskSlot 资源池进行对资源进行有效管理。
Slots
Flink 中每一个 TaskManager 都是一个 JVM 进程,他可能会在独立的线程上执行一个或多个 subtask
为了控制一个 TaskManager 能接收多少个 task,TaskManager通过 task slot 来进行控制, 一个TaskManager至少有一个 slot
Slot 共享
默认情况下,Flink 允许 subtasks共享 slot
条件是它们都来自同一个 Job 的不同 task 的 subtask。结果可能是一个 slot 持有该 job的整个pipeline。
优点
Flink 集群需要的任务槽与作业中使用的最高并行度正好相同(前提,保持默认SlotSharingGroup)。也就是说我们不需要再去计算一个程序总共会起多少个task了。
更容易获得更充分的资源利用。如果没有slot共享,那么非密集型操作source/flatmap就会占用同密集型操作 keyAggregation/sink 一样多的资源。如果有slot共享,将task的2个并行度增加到6个,能充分利用slot资源,同时保证每个TaskManager能平均分配到重的subtasks。
SlotSharingGroup[soft]
SlotSharingGroup 是Flink中用来实现 slot 共享的类,它尽可能地让 subtasks 共享一个slot。
保证同一个 group 的并行度相同的 sub-tasks 共享同一个slots。
算子的默认group为default [即默认一个 Job下 的 subtask都可以共享一个 slot]
为了防止不合理的共享,用户也能通过API来强制指定 operator 的共享组
比如:someStream.filter(…).slotSharingGroup(“group1”);就强制指定了filter的slot共享组为group1。
怎么确定一个未做SlotSharingGroup设置算子的SlotSharingGroup什么呢(根据上游算子的group 和自身是否设置group共同确定)。适当设置可以减少每个slot运行的线程数,从而整体上减少机器的负载。