1.什么是Apache Flink(为什么使用 Flink 替代 Spark?)

        Apache Flink
是一个开源的基于流的有状态计算框架。它是分布式地执行的,具备低延迟、高吞吐的优秀性能,并且非常擅长处理有状态的复杂计算逻辑场景。

2.Flink 的核心概念

        Flink 的核心概念主要有四个:Event Streams、State、Time 和 Snapshots。               
      

* Event Streams:即事件流,事件流可以是实时的也可以是历史的。Flink
是基于流的,但它不止能处理流,也能处理批,而流和批的输入都是事件流,差别在于实时与批量。
* State:Flink
擅长处理有状态的计算。通常的复杂业务逻辑都是有状态的,它不仅要处理单一的事件,而且需要记录一系列历史的信息,然后进行计算或者判断。
* Time:最主要处理的问题是数据乱序的时候,一致性如何保证。
* Snapshots:实现了数据的快照、故障的恢复,保证数据一致性和作业的升级迁移等。
3.作业在很多情况下有可能会失败。失败之后重新去运行时,我们如何保证数据的一致性?

        Flink 基于 Chandy-Lamport 算法,会把分布式的每一个节点的状态保存到分布式文件系统里面作为
Checkpoint(检查点),过程大致如下。首先,从数据源端开始注入 Checkpoint Barrier,它是一种比较特殊的消息。

        然后它会跟普通的事件一样随着数据流去流动,当 Barrier 到达算子之后,这个算子会把它当前的本地状态进行快照保存,当 Barrier
流动到 Sink,所有的状态都保存完整了之后,它就形成一个全局的快照。

        这样当作业失败之后,就可以通过远程文件系统里面保存的 Checkpoint 来进行回滚:先把 Source 回滚到 Checkpoint
记录的 offset,然后把有状态节点当时的状态回滚到对应的时间点,进行重新计算。这样既可以不用从头开始计算,又能保证数据语义的一致性。

4.Flink的时间语义

* Event Time:事件创建的时间
* Ingestion Time:数据进入Flink的时间
* Processing Time:执行操作算子的本地系统时间,与机器相关
5.Flink的API可分为哪几层?

* SQL & Table API
同时适用于批处理和流处理,这意味着你可以对有界数据流和无界数据流以相同的语义进行查询,并产生相同的结果。除了基本查询外,
它还支持自定义的标量函数,聚合函数以及表值函数,可以满足多样化的查询需求。
* DataStream & DataSet API 是 Flink 数据处理的核心 API,支持使用 Java 语言或 Scala
语言进行调用,提供了数据读取,数据转换和数据输出等一系列常用操作的封装。
* Stateful Stream Processing 是最低级别的抽象,它通过 Process Function 函数内嵌到 DataStream
API 中。 Process Function 是 Flink 提供的最底层 API,具有最大的灵活性,允许开发者对于时间和状态进行细粒度的控制。
6.Flink 运行时组件

1) 作业管理器(JobManager)

* 控制一个应用程序执行的主进程,也就是说,每个应用程序都会被一个不同的Jobmanager所控制执行
* Jobmanager会先接收到要执行的应用程序,这个应用程序会包括:作业图( Job Graph)、逻辑数据流图( ogical dataflow
graph)和打包了所有的类、库和其它资源的JAR包。
*
Jobmanager会把Jobgraph转换成一个物理层面的数据流图,这个图被叫做“执行图”(Executiongraph),包含了所有可以并发执行的任务。Job
Manager会向资源管理器(Resourcemanager)请求执行任务必要的资源,也就是任务管理器(Taskmanager)上的插槽slot。一旦它获取到了足够的资源,就会将执行图分发到真正运行它们的
Taskmanager上。而在运行过程中Jobmanagera会负责所有需要中央协调的操作,比如说检查点(checkpoints)的协调。
2) 任务管理器(TaskManager)

* Flink中的工作进程。通常在
Flink中会有多个Taskmanager运行,每个Taskmanager都包含了一定数量的插槽(slots)。插槽的数量限制了Taskmanager能够执行的任务数量。
* 启动之后,Taskmanager会向资源管理器注册它的插槽;收到资源管理器的指令后,
Taskmanager就会将一个或者多个插槽提供给Jobmanager调用。Jobmanager就可以向插槽分配任务(tasks)来执行了。
* 在执行过程中,一个Taskmanager可以跟其它运行同一应用程序的Taskmanager交换数据。
3) 资源管理器(ResourceManager)

* 主要负责管理任务管理器(TaskManager)的插槽(slot)Taskmanger插槽是Flink中定义的处理资源单元。
* Flink为不同的环境和资源管理工具提供了不同资源管理器,比如YARN、K8s,以及 standalone部署。
* 当Jobmanager申请插槽资源时,Resourcemanager会将有空闲插槽的Taskmanager分配给Jobmanager。如果
Resourcemanager没有足够的插槽来满足 Jobmanager的请求,它还可以向资源提供平台发起会话,以提供启动 Taskmanager进程的容器。
4) 分发器(Dispatcher)

* 可以跨作业运行,它为应用提交提供了REST接口。
* 当一个应用被提交执行时,分发器就会启动并将应用移交给Jobmanage。
* Dispatcher他会启动一个WebUi,用来方便地展示和监控作业执行的信息。
7.Flink任务提交流程

8.任务提交流程(YARN)

* Flink任务提交后,Client向HDFS上传Flink的Jar包和配置
* 随后向Yarn ResourceManager提交任务,ResourceManager分配Container资源并通知对应的NodeManager启动
* ApplicationMaster,ApplicationMaster启动后加载Flink的Jar包和配置构建环境
* 然后启动JobManager,之后ApplicationMaster向ResourceManager申请资源启动 TaskManager
*
ResourceManager分配Container资源后,由ApplicationMaster通知资源所在节点的NodeManager启动TaskManager
* NodeManager加载Flink的Jar包和配置构建环境并启动TaskManager
* TaskManager启动后向JobManager发送心跳包,并等待JobManager向其分配任务。
9.Flink的执行图

Flink中的执行图可以分成四层: Streamgraph -> Jobgraph -> Executiongraph -> 物理执行图

* Streamgraph:是根据用户通过 Stream API编写的代码生成的最初的图。用来表示程序的拓扑结构。
* Jobgraph:Streamgraph经过优化后生成了 Jobgraph,提交给 Jobmanager的数据结构。主要的优化为,将多个符合条件的节点
chain在一起作为一个节点。
* Execution Graph:Jobmanager根据 Jobgraph生成,是 Jobgraph的并行化版本,是调度层最核心的数据结构。
* 物理执行图:Jobmanager根据 Executiongraph对Job进行调度后,在各个Taskmanager上部署Task后形成的“图
”,并不是一个具体的数据结构。
10.Flink的分区策略

11.Flink 的状态分为哪两类

        作为对状态支持比较好的系统,Flink内部提供了可以使用的很多种可选的状态原语。从大的角度看,
所有状态原语可以分为KeyedState和OperatorState 两类。

12.KeyedState都有哪几类

        Keyed State 可以进一步划分为下面的 5 类,它们分别是

* 比较常用的:ValueState、ListState、MapState
* 不太常用的:ReducingState 和 AggregationState
13.Flink中watermark的概念

        watermark是一种衡量Event Time进展的机制,它是数据本身的一个隐藏属性。通常基于Event
Time的数据,自身都包含一个timestamp.watermark是用于处理乱序事件的,而正确的处理乱序事件,通常用watermark机制结合window来实现。

        流处理从事件产生,到流经source,再到operator,中间是有一个过程和时间的。虽然大部分情况下,流到operator的数据都是按照事件产生的时间顺序来的,但是也不排除由于网络、背压等原因,导致乱序的产生(out-of-order或者说late
element)。

        但是对于late
element,我们又不能无限期的等下去,必须要有个机制来保证一个特定的时间后,必须触发window去进行计算了。这个特别的机制,就是watermark。

14.什么是Flink的全局快照

       全局快照首先是一个分布式应用,它有多个进程分布在多个服务器上;其次,它在应用内部有自己的处理逻辑和状态;第三,应用间是可以互相通信的;第四,在这种分布式的应用,有内部状态,硬件可以通信的情况下,某一时刻的全局状态,就叫做全局的快照。

15.为什么需要全局快照

* 第一,用它来做检查点,可以定期对全局状态做备份,当应用程序故障时,就可以拿来恢复;
* 第二,做死锁检测,进行快照后当前的程序继续运行,然后可以对快照进行分 析,看应用程序是不是存在死锁状态,如果是就可以进行相应的处理。
16.Flink的容错机制

* Exactly once,是指每条 event 会且只会对 state 产生一次影响,这里的“一次”并非端到端的严格一次,而是指在 Flink
内部只处理一次,不包括 source和 sink 的处理。
* At least once,是指每条 event 会对 state 产生最少一次影响,也就是存在重复处理的可能。
* At most once,是指每条 event 会对 state 产生最多一次影响,就是状态可能会在出错时丢失。
17.Flink是如何实现End-To-End Exactly-once的?

        Flink通过状态和两次提交协议来保证了端到端的exactly-once语义

* Source:支持数据的replay,如Kafka的offset。
* Transformation:借助于checkpoint
* Sink:Checkpoint + 两阶段事务提交
18.解释下两阶段提交?

* 一旦Flink开始做checkpoint操作,就会进入pre-commit
“预提交”阶段,同时JobManager的Coordinator会将Barrier注入数据流中。
* 当所有的barrier在算子中成功进行一遍传递(就是Checkpoint完成),并完成快照后,“预提交”阶段完成。
* 等所有的算子完成“预提交”,就会发起一个commit “提交”动作,但是任何一个“预提交” 失败都会导致Flink回滚到最近的checkpoint。
19.两阶段提交API

* beginTransaction:在开启事务之前,我们在目标文件系统的临时目录中创建一个临时文件,后面在处理数据时将数据写入此文件。
* preCommit:在预提交阶段,刷写(flush)文件,然后关闭文件,之后就不能写入到文件了,我们还将为属于下一个检查点的任何后续写入启动新事务。
* commit:在提交阶段,我们将预提交的文件原子性移动到真正的目标目录中,请注意,这回增加输出数据可见性的延迟。
* abort:在中止阶段,我们删除临时文件。
20.Flink 的 checkpoint 存在哪里?

        可以是内存,文件系统,或者 RocksDB。

21.海量 key 去重

        如果是海量数据的话,Set结构是不现实的,可以考虑使用布隆过滤器来去重。

22.Flink 的 checkpoint 机制对比 spark 有什么不同和优势?

        spark streaming 的 checkpoint 仅仅是针对 driver 的故障恢复做了数据和元数据的 checkpoint。而
flink 的 checkpoint 机制 要复杂了很多,它采用的是轻量级的分布式快照,实现了每个算子的快照,及流动中的数据的快照。

23.Flink CEP 编程中当状态没有到达的时候会将数据保存在哪里?

        在 Flink CEP 的处理逻辑中,状态没有满足的和迟到的数据,都会存储在一个 Map
数据结构中,也就是说,如果我们限定判断事件序列的时长为 5 分钟,那么内存中就会存储 5 分钟的数据。

24.Flink 程序在面对数据高峰期时如何处理?

         使用大容量的 Kafka 把数据先放到消息队列里面作为数据源,再使用Flink 进行消费,不过这样会影响到一点实时性。

25.Flink 的运行必须依赖 Hadoop组件吗?

        Flink可以完全独立于Hadoop,在不依赖Hadoop组件下运行。但是做为大数据的基础设施,Hadoop体系是任何大数据框架都绕不过去的。Flink可以集成众多Hadooop
组件,例如Yarn、Hbase、HDFS等等。例如,Flink可以和Yarn集成做资源调度,也可以读写HDFS,或者利用HDFS做检查点。

26.Flink 资源管理中 Task Slot 的概念

        在Flink架构角色中我们提到,TaskManager是实际负责执行计算的Worker,TaskManager 是一个 JVM
进程,并会以独立的线程来执行一个task或多个subtask。为了控制一个 TaskManager 能接受多少个 task,Flink 提出了 Task
Slot 的概念。

        简单的说,TaskManager会将自己节点上管理的资源分为不同的Slot:固定大小的资源子集。这样就避免了不同Job的Task互相竞争内存资源,但是需要主要的是,Slot只会做内存的隔离。没有做CPU的隔离。

27.Flink的重启策略都有哪些?

*
固定延迟重启策略(Fixed Delay Restart Strategy)

*
故障率重启策略(Failure Rate Restart Strategy)

*
没有重启策略(No Restart Strategy)

*
Fallback重启策略(Fallback Restart Strategy)

28.Flink中的广播变量,使用时需要注意什么?

         我们知道Flink是并行的,计算过程可能不在一个 Slot
中进行,那么有一种情况即:当我们需要访问同一份数据。那么Flink中的广播变量就是为了解决这种情况。

        我们可以把广播变量理解为是一个公共的共享变量,我们可以把一个dataset
数据集广播出去,然后不同的task在节点上都能够获取到,这个数据在每个节点上只会存在一份。

29.Flink的内存模型

30.数据倾斜问题

1.keyBy之前发生数据倾斜

       
如果keyBy之前就存在数据倾斜,上游算子的某些实例可能处理的数据较多,某些实例可能处理的数据较少,产生该情况可能是因为数据源的数据本身就不均匀,例如由于某些原因Kafka的topic中某些partition的数据量较大,某些partition的数据量较少。对于不存在keyBy的Flink任务也会出现该情况。

       
这种情况,需要让Flink任务强制进行shuffle。使用shuffle、rebalance、rescale算子即可将数据均匀分配,从而解决数据倾斜的问题。

2.keyBy之后无开窗聚合数据倾斜

        map端使用状态先预聚合,达到一定时间或者一定size后再同一输出(localkeyby)。

3.keyBy后的窗口聚合操作存在数据倾斜

        因为使用了窗口,变成了有界数据的处理,窗口默认是触发时才会输出一条结果发往下游,所以可以使用两阶段聚合的方式:

        第一阶段聚合:key拼接随机数前缀或后缀,进步keyby、开窗、聚合。

        第二阶段聚合:去掉随机数前缀或后缀,按照原来的key及windowEnd作keyby、聚合。

31.Flink连接API

* union 多流合并,类型一致
* connect 两条流分别处理,类型可不一致,可共享状态
* join 相当于innerjoin
* coGroup 实现左外连接,第一个流没有join上,也要输出
32.Flink-On-Yarn常见的提交模式有哪些,分别有什么优缺点?

1.yarn-session模式:

        这种方式需要先启动集群,然后在提交作业,接着会向yarn申请一块空间后,资源永远保持不变。如果资源满了,下一个就任务就无法提交,只能等到yarn中其中一个作业完成后,释放了资源,那下一个作业才会正常提交,这种方式资源被限制在session中,不能超过,比较适合特定的运行环境或测试环境。

2.per-job模式:

        这种方式直接在yarn上提交任务运行Flink作业,这种方式的好处是一个任务会对应一个job,即每提交一个作业会根据自身的情况,向yarn中申请资源,直到作业执行完成,并不会影响下一个作业的正常运行,除非是yarn上面没有任何资源的情况下。一般生产环境是采用此方式运行。这种方式需要保证集群资源足够。

33.Flink如何处理迟到数据

* watermark可以设置延迟时间
* window的allowedLateness方法,可以设置窗口允许处理迟到数据的时间
* window的sideOutputLateData方法,可以将迟到的数据写入侧输出流
34.Flink任务延迟高如何解决

        在Flink的后台任务管理中,我们可以看到Flink的那个算子和task出现了反压。最主要的手段是资源调优和算子调优。例如调大并发,增加运行任务的资源。缩短窗口时长。

35.Flink Operator Chains

        为了更高效地分布式执行,Flink会尽可能地将operator的subtask链接(chain)在一起形成task。每个task在一个线程中执行。将operators链接成task是非常有效的优化:它能减少线程之间的切换,减少消息的序列化/反序列化,减少数据在缓冲区的交换,减少了延迟的同时提高整体的吞吐量。这就是我们所说的算子链。其实就是尽量把操作逻辑放入到同一个subtask里面也就是一个槽TaskSolt。

36.Flink什么情况下才会把Operator chain在一起形成算子链?

* 上下游并行度一致
* 下游数据没有其他的输入
* 上下游节点都在同一个soltgroup中,默认是一样的,如果不是,单独指定的算子资源,会独占TaskSolt
* 没有keyed操作
* 数据发送策略是forward
* 用户没有禁用chain
37.Flink中应用在tableAPI中的UDF有几种?

* scalar function:针对一条record的一个字段的操作,返回一个字段
* table function:针对一条record的一个字段的操作,返回多个字段
* aggregate function:针对多条记录的一个字段操作,返回一条记录

技术
下载桌面版
GitHub
Gitee
SourceForge
百度网盘(提取码:draw)
云服务器优惠
华为云优惠券
腾讯云优惠券
阿里云优惠券
Vultr优惠券
站点信息
问题反馈
邮箱:[email protected]
吐槽一下
QQ群:766591547
关注微信