1、简单介绍flink
Flink 是一个框架和分布式处理引擎,用于对无界和有界数据流进行有状态计算。提供了数据分布、容错机制以及资源管理等核心功能。
2、flink与streaming的区别
-
架构模型: Spark Streaming 在运行时的主要角色包括: Master、Worker、Driver、Executor, Flink 在运行时主要包含: Jobmanager、Taskmanager和Slot。
-
任务调度: Spark Streaming 连续不断的生成微小的数据批次,构建有向无环图DAG, Spark Streaming 会依次创建 DStreamGraph、JobGenerator、JobScheduler。 Flink 根据用户提交的代码生成 StreamGraph,经过优化生成 JobGraph,然后提交给 JobManager进行处理, JobManager 会根据 JobGraph 生成 ExecutionGraph,ExecutionGraph 是 Flink 调度最核心的数据结构,JobManager 根据 ExecutionGraph 对 Job 进行调度。
-
时间机制: Spark Streaming 支持的时间机制有限,只支持处理时间。 Flink 支持了流处理程序在时间上的三个定义:处理时间、事件时间、注入时间。 同时也支持 watermark 机制来处理滞后数据。
-
容错机制 对于 Spark Streaming 任务,我们可以设置 checkpoint, 然后假如发生故障并重启,我们可以从上次 checkpoint 之处恢复, 但是这个行为只能使得数据不丢失,可能会重复处理,不能做到恰好一次处理语义。 Flink 则使用两阶段提交协议来解决这个问题。
3、flink的checkpoint问题
Flink 为了达到容错和 exactly-once 语义的功能,定期把 state 持久化下来,这个过程就叫做 checkpoint ,它是 Flink Job 在某一时刻全局状态的快照。 ck过程:
每一个 Flink 作业都会产生一个 JobManager ,JobManager 里面又会有一个 checkpoint
coordinator 来管理整个 checkpoint 的过程,我们可以设置一个时间间隔让 checkpoint
coordinator 将一个 checkpoint 的事件发送给每一个 Container 中的 source task,也就是
第一个任务(对应并行图中的 task1,task2)。
当某个 Source 算子收到一个 Barrier 时,它会暂停自身的数据处理,然后将自己的当前
state 制作成 snapshot(快照),并保存到指定的持久化存储中,最后向
CheckpointCoordinator 异步发送一个 ack(Acknowledge character --- 确认字符),同时
向自身所有下游算子广播该 Barrier 后恢复自身的数据处理。
每个算子按照上面不断制作 snapshot 并向下游广播,直到最后 Barrier 传递到 sink 算子,
此时快照便制作完成。这时候需要注意的是,上游算子可能是多个数据源,对应多个 Barrier 需要
全部到齐才一次性触发 checkpoint ,所以在遇到 checkpoint 时间较长的情况时,有可能是因
为数据对齐需要耗费的时间比较长所造成的。
4、flink的各个组件有什么作用
-
JobManager 其中JobManager扮演着集群中的管理者Master的角色,它是整个集群的协调者,负责接收Flink Job,协调检查点,Failover 故障恢复等,同时管理Flink集群中从节点TaskManager。
-
TaskManager TaskManager是实际负责执行计算的Worker,在其上执行Flink Job的一组Task,每个TaskManager负责管理其所在节点上的资源信息,如内存、磁盘、网络,在启动的时候将资源的状态向JobManager汇报。
-
Client Client是Flink程序提交的客户端,当用户提交一个Flink程序时,会首先创建一个Client,该Client首先会对用户提交的Flink程序进行预处理,并提交到Flink集群中处理,所以Client需要从用户提交的Flink程序配置中获取JobManager的地址,并建立到JobManager的连接,将Flink Job提交给JobManager。
5、slot概念
在Flink架构角色中我们提到,TaskManager是实际负责执行计算的Worker,TaskManager 是一个 JVM 进程,并会以独立的线程来执行一个task或多个subtask。为了控制一个 TaskManager 能接受多少个 task,Flink 提出了 Task Slot 的概念。
简单的说,TaskManager会将自己节点上管理的资源分为不同的Slot:固定大小的资源子集。这样就避免了不同Job的Task互相竞争内存资源,但是需要主要的是,Slot只会做内存的隔离。没有做CPU的隔离。
6、背压
如果生产者端使用无界的buffer,当我们的生产者生产速度远大于消费者消费的速度时,生产者端的数据会因为消费端的消费能力低下而导致数据积压,最终导致 OOM 的产生。
- 静态流控:就是当生产者比消费者的 TPS 多时,此时我们采用溢写的方式,使用 batch 封装好我们的数据按批次进行发送,每次发送完成后再 sleep 一段时间,这个时间的计算方式是 left(剩余的数据)/ tps,但是这个做法是很难去预估系统的情况的。确定:需要预估速度,不能动态调整
- 动态流控:Flink 的数据交换大致分为三种,一种是同一个 Task 的数据交换,另一种是 不同 Task 同 JVM 下的数据交换。第三种就是不同 Task 且不同 JVM 之间的交换。
-
第一种方式:forward strategy 方式,就是同一个 Task 的数据交换,主要就是为了避免了序列化和网络的开销,造成不必要的资源浪费。
-
第二种数据交换的方式就是数据会先通过一个 record Writer进行序列化,传递给 Result Partition ,之后数据会通过 local channel 传递给另外一个 Task 的 Input Gate 里面进行反序列化,然后推送给 Record Reader 之后进行操作。
-
* 第三种数据交换涉及到了不同的 JVM,所以会有一定的网络开销,和第二种的区别就是通过netty把数据推送到远程端的 Task 上。我们可以看到backlog 的作用其实只是为了让消费端感知到我们生产端的情况, event1 连带一个 backlog = 1 推送给了 TaskB。event1 被 TaskB 接收后,TaskB会返回一个 ack 给 TaskA,同时返回一个credit = 3,这个是告知 TaskA 它还能接收多少条数据。Flink 就是通过这种互相告知的方式,来让生产者和消费者都能感知到对方的状态。
7、flink的内存组成
JVM 是一个非常复杂的系统,当其内存不足时会造成 OOM ,进而导致系统的崩溃。
Flink 在拿到我们分配的内存之后会先分配一个 cut off 预留内存,从而保证系统的安全性。
Netword buffers 其实就是之前所提到的有界 buffer,momery manager 是一个内存池,这部分的内存可以设置为堆内或者堆外的内存,当然在流式作业中我们一般设置其为堆外内存,而 Free 部分就是提供给用户使用的内存块。