1、Flink 相比传统的 Spark Streaming 有什么区别?
参考答案:
这个问题是一个非常宏观的问题,因为两个框架的不同点非常之多。但是在面试时有非常重要的一点一定要回答出来:Flink 是标准的实时处理引擎,基于事件驱动。而 Spark Streaming 是微批(Micro-Batch)的模型。
下面我们就分几个方面介绍两个框架的主要区别:
1. 架构模型
Spark Streaming 在运行时的主要角色包括:Master、Worker、Driver、Executor,Flink 在运行时主要包含:Jobmanager、Taskmanager和Slot。
2. 任务调度
Spark Streaming 连续不断的生成微小的数据批次,构建有向无环图DAG,Spark Streaming 会依次创建 DStreamGraph、JobGenerator、JobScheduler。
Flink 根据用户提交的代码生成 StreamGraph,经过优化生成 JobGraph,然后提交给 JobManager进行处理,JobManager 会根据 JobGraph 生成 ExecutionGraph,ExecutionGraph 是 Flink 调度最核心的数据结构,JobManager 根据 ExecutionGraph 对 Job 进行调度。
3. 时间机制
Spark Streaming 支持的时间机制有限,只支持处理时间。 Flink 支持了流处理程序在时间上的三个定义:处理时间、事件时间、注入时间。同时也支持 watermark 机制来处理滞后数据。
4. 容错机制
对于 Spark Streaming 任务,我们可以设置 checkpoint,然后假如发生故障并重启,我们可以从上次 checkpoint 之处恢复,但是这个行为只能使得数据不丢失,可能会重复处理,不能做到恰好一次处理语义。
Flink 则使用两阶段提交协议来解决这个问题。
2、Flink 三种时间语义是什么,分别说出应用场景?
参考答案:
1. Event Time:这是实际应用最常见的时间语义。
2. Processing Time:没有事件时间的情况下,或者对实时性要求超高的情况下。
3. Ingestion Time:存在多个 Source Operator 的情况下,每个 Source Operator
可以使用自己本地系统时钟指派 Ingestion Time。后续基于时间相关的各种操作,
都会使用数据记录中的 Ingestion Time。
3、Flink CEP 编程中当状态没有到达的时候会将数据保存在哪里?
参考答案:
在流式处理中,CEP 当然是要支持 EventTime 的,那么相对应的也要支持数据的迟到现象,也就是 watermark 的处理逻辑。CEP 对未匹配成功的事件序 列的处理,和迟到数据是类似的。在 Flink CEP 的处理逻辑中,状态没有满足的和迟到的数据,都会存储在一个 Map 数据结构中,也就是说,如果我们限定判断事件 序列的时长为 5 分钟,那么内存中就会存储 5 分钟的数据,这在我看来,也是对内 存的极大损伤之一。
4、说说 Flink 的常用算子?
参考答案:
Map:DataStream → DataStream,输入一个参数产生一个参数,map的功能是对输入的参数进行转换操作。Filter:过滤掉指定条件的数据。KeyBy:按照指定的key进行分组。Reduce:用来进行结果汇总合并。Window:窗口函数,根据某些特性将每个key的数据进行分组(例如:在5s内到达的数据)。
5、Flink有没有重启策略?说说有哪几种?
参考答案:
Flink 实现了多种重启策略。
- 固定延迟重启策略(Fixed Delay Restart Strategy)
- 故障率重启策略(Failure Rate Restart Strategy)
- 没有重启策略(No Restart Strategy)
- Fallback重启策略(Fallback Restart Strategy)
6、Flink的并行度了解吗?Flink的并行度设置是怎样的?
参考答案:
Flink中的任务被分为多个并行任务来执行,其中每个并行的实例处理一部分数据。这些并行实例的数量被称为并行度。
我们在实际生产环境中可以从四个不同层面设置并行度:
- 操作算子层面(Operator Level)
- 执行环境层面(Execution Environment Level)
- 客户端层面(Client Level)
- 系统层面(System Level)
需要注意的优先级:算子层面>环境层面>客户端层面>系统层面。
7、说说 Flink的内存管理是如何做的?
参考答案:
Flink 并不是将大量对象存在堆上,而是将对象都序列化到一个预分配的内存块上。此外,Flink大量的使用了堆外内存。如果需要处理的数据超出了内存限制,则会将部分数据存储到硬盘上。Flink 为了直接操作二进制数据实现了自己的序列化框架。
理论上Flink的内存管理分为三部分:
- Network Buffers:这个是在TaskManager启动的时候分配的,这是一组用于缓存网络数据的内存,每个块是32K,默认分配2048个,可以通过“taskmanager.network.numberOfBuffers”修改
- Memory Manage pool:大量的Memory Segment块,用于运行时的算法(Sort/Join/Shuffle等),这部分启动的时候就会分配。下面这段代码,根据配置文件中的各种参数来计算内存的分配方法。(heap or off-heap,这个放到下节谈),内存的分配支持预分配和lazy load,默认懒加载的方式。
- User Code,这部分是除了Memory Manager之外的内存用于User code和TaskManager本身的数据结构。
8、能否详细解释一下其中的 数据流、流批一体、容错能力等概念?
参考答案:
数据流:
所有产生的数据都天然带有时间概念,把 事件 按照时间顺序排列起来,就形成了一个事件流,也被称作数据流。
流批一体:
有界数据和无界数据。
有界数据,就是在一个确定的时间范围内的数据流,有开始,有结束,一旦确定就不会再改变,一般 批处理用来处理有界数据,如上图的 bounded stream。
无界数据,就是持续产生的数据流,数据是无限的,有开始,无结束,一般流处理用来处理无界数据。如图 unbounded stream。
Flink 的设计思想是以流为核心,批是流的特例,擅长处理 无界 和 有界 数据, Flink 提供 精确的时间控制能力 和 有状态 计算机制,可以轻松应对无界数据流,同时 提供窗口处理有界数据流。所以被成为流批一体。
容错能力:
在分布式系统中,硬件故障、进程异常、应用异常、网络故障等异常无处不在,Flink 引擎必须保证故障发生后 不仅可以 重启 应用程序,还要 确保 其内部状态保持一致,从最后一次正确的时间点重新出发。
Flink 提供 集群级容错 和 应用级容错 能力。
集群级容错: Flink 与 集群管理器紧密连接,如 YARN、Kubernetes,当进程挂掉后,自动重启新进程接管之前的工作。同时具备高可用性可消除所有单点故障,
应用级容错:Flink 使用 轻量级分布式快照,设计检查点(checkpoint)实现可靠容错。
Exactly-once
9、Flink是如何做到高效的数据交换的?
参考答案:
在一个Flink Job中,数据需要在不同的task中进行交换,整个数据交换是有 TaskManager 负责的,TaskManager 的网络组件首先从缓冲buffer中收集records,然后再发送。Records 并不是一个一个被发送的,而是积累一个批次再发送,batch 技术可以更加高效的利用网络资源。
10、Flink 的 kafka 连接器有什么特别的地方?
参考答案:
Flink源码中有一个独立的connector模块,所有的其他connector都依赖于此模块,Flink 在1.9版本发布的全新kafka连接器,摒弃了之前连接不同版本的kafka集群需要依赖不同版本的connector这种做法,只需要依赖一个connector即可。