轻松入门进阶Flink第十课 Flink 面试

86 篇文章 47 订阅

第39讲:Flink 面试-基础篇

到目前为止,关于 Flink 的学习我们就告一段落了,接下来我们将进入最后一个面试模块的学习。在当前大背景下,面试这一关是求职者必须要面对的,也能从侧面考察对 Flink 的掌握情况,最后一模块将结合部分实际面试中出现的问题,进行详细分析,帮助大家顺利拿到 Offer。

最后一个面试模块分为了 4 个课时:

  • Flink 面试基础篇,包含了 Flink 的整体介绍、核心概念、算子等考察点;

  • Flink 面试进阶篇,包含了 Flink 中的数据传输、容错机制、序列化、数据热点、反压等实际生产环境中遇到的问题等考察点;

  • Flink 面试源码篇,包含了 Flink 的核心代码实现、Job 提交流程、数据交换、分布式快照机制、Flink SQL 的原理等考察点;

  • Flink 面试方案设计篇,主要是生产环境中常见业务场景下的解决方案设计。

本课时将分析 Flink 面试基础相关的面试题,总结出了经常面试的 12 道题。

面试题 1:请介绍一下 Flink。

这道题是一道很简单的入门题,考察我们队 Flink 整体的掌握情况,我们应该从以下几个基本的概念入手。

Flink 是大数据领域的分布式实时和离线计算引擎,其程序的基础构建模块是流(Streams)和转换(Transformations),每一个数据流起始于一个或多个 Source,并终止于一个或多个 Sink。数据流类似于有向无环图(DAG)。

Flink 提供了诸多高抽象层的 API 以便用户编写分布式任务:

  • DataSet API,对静态数据进行批处理操作,将静态数据抽象成分布式的数据集,用户可以方便地使用 Flink 提供的各种操作符对分布式数据集进行处理,支持 Java、Scala 和 Python;

  • DataStream API,对数据流进行流处理操作,将流式的数据抽象成分布式的数据流,用户可以方便地对分布式数据流进行各种操作,支持 Java 和 Scala;

  • Table API,对结构化数据进行查询操作,将结构化数据抽象成关系表,并通过类 SQL 的 DSL 对关系表进行各种查询操作,支持 Java 和 Scala。

此外,Flink 还针对特定的应用领域提供了领域库,例如,Flink ML,Flink 的机器学习库提供了机器学习 Pipelines API 并实现了多种机器学习算法;Gelly、Flink 的图计算库提供了图计算的相关 API 及多种图计算算法的实现。

面试题 2:Flink 的主要特性是什么?

这道题考察我们在使用 Flink 的过程中用到的哪些强大的特性。我们在开篇词和第 01 课时“Flink 的应用场景和架构模型”中提到过,Flink 的主要特性包括:批流一体、Exactly-Once、强大的状态管理等。

同时,Flink 还支持运行在包括 Yarn、Mesos、Kubernetes 在内的多种资源管理框架上。Flink 可以扩展到数千核心,其状态可以达到 TB 级别,且仍能保持高吞吐、低延迟的特性。

面试题 3:Flink 的适用场景有哪些?

这道题是一道很典型的考察我们掌握 Flink 的广度的问题,要求我们开发者不要局限在自己的一小块业务中,能主动地去学习其他人是如何玩转 Flink 的。我们可以从以下几个方面回答:

Flink 从诞生之初就因为其独特的流式计算特性迅速被各个公司采用到各行各业中,主要的应用场景包括:

  • 实时数据计算

  • 实时数据仓库和 ETL

  • 事件驱动型场景,如告警、监控

此外,随着 Flink 对机器学习的支持越来越完善,还可以被用作机器学习和人工智能领域的引擎。

面试题 4:Flink 和 Spark Streaming 的异同点有哪些?

分析:这是一个非常宏观的面试题,因为两个框架的不同点非常之多。但是在面试时有非常重要的一点一定要回答出来:Flink 是标准的实时处理引擎,基于事件驱动;而 Spark Streaming 是微批(Micro-Batch)的模型。

在“03 | Flink 的编程模型与其他框架比较”课时中也讲过 Flink 的优势及与其他框架的区别。

  • 架构

Spark Streaming 的架构是基于 Spark 的,它的本质是微批处理,每个 batch 都依赖 Driver,我们可以把 Spark Streaming 理解为时间维度上的 Spark DAG。

Flink 也采用了经典的主从模式,DataFlow Graph 与 Storm 形成的拓扑 Topology 结构类似,Flink 程序启动后,会根据用户的代码处理成 Stream Graph,然后优化成为 JobGraph,JobManager 会根据 JobGraph 生成 ExecutionGraph。ExecutionGraph 才是 Flink 真正能执行的数据结构,当很多个 ExecutionGraph 分布在集群中,就会形成一张网状的拓扑结构

  • 容错

针对 Spark Streaming 任务,我们可以配置对应的 Checkpoint,也就是保存点。当任务出现 Failover 的时候,会从 Checkpoint 重新加载,使得数据不丢失。但是这个过程会导致原来的数据重复处理,不能做到“只处理一次”语义。

Flink 基于两阶段提交实现了精确的一次处理语义,我们在第 14 课时 “Flink Exactly-once 实现原理解析” 中有过详细的讲解。

  • 反压(BackPressure)

反压是分布式处理系统中经常遇到的问题,当消费者速度低于生产者的速度时,则需要消费者将信息反馈给生产者使得生产者的速度能和消费者的速度进行匹配。

Spark Streaming 为了实现反压这个功能,在原来的架构基础上构造了一个“速率控制器”,“速率控制器”会根据几个属性,比如任务的结束时间、处理时长、处理消息的条数等计算一个速率。在实现控制数据的接收速率中用到了一个经典的算法,即“PID 算法”。

Flink 没有使用任何复杂的机制来解决反压问题,Flink 在数据传输过程中使用了分布式阻塞队列。我们知道在一个阻塞队列中,当队列满了以后发送者会被天然阻塞住,这种阻塞功能相当于给这个阻塞队列提供了反压的能力。

  • 时间机制

Spark Streaming 支持的时间机制有限,只支持处理时间。 Flink 支持了流处理程序在时间上的三个定义:处理时间、事件时间、注入时间;同时也支持 watermark 机制来处理滞后数据。

面试题 5:请谈谈 Flink 的组件栈和数据流模型。

Flink 的组件栈和数据流模型是我们使用 Flink 的基础,只有了解这些组件栈和数据模型才能入手进行 Flink 项目的开发。

Drawing 0.png

Flink 自身提供了不同级别的抽象来支持我们开发流式或者批量处理程序,上图描述了 Flink 支持的 4 种不同级别的抽象。

对于我们开发者来说,大多数应用程序不需要上图中的最低级别的 Low-level 抽象,而是针对 Core API 编程,比如DataStream API(有界/无界流)和DataSet API(有界数据集)。这些流畅的 API 提供了用于数据处理的通用构建块,比如各种形式用户指定的转换、连接、聚合、窗口、状态等。

Table API 和 SQL是 Flink 提供的更为高级的 API 操作,Flink SQL 是 Flink 实时计算为简化计算模型,降低了用户使用实时计算门槛而设计的一套符合标准 SQL 语义的开发语言。

Drawing 1.png

Flink 程序的基本构建是数据输入来自一个 Source,Source 代表数据的输入端,经过 Transformation 进行转换,然后在一个或者多个 Sink 接收器中结束。数据流(Stream)就是一组永远不会停止的数据记录流,而转换(Transformation)是将一个或多个流作为输入,并生成一个或多个输出流的操作。在执行时,Flink 程序映射到 Streaming Dataflows,由流(Streams)和转换操作(Transformation Operators)组成。

面试题 6:请谈谈 Flink 中的角色和作用各是什么?

这道题考察我们生产环境中 Flink 的集群是如何工作的,开发者有没有主动去研究过生产环境 Flink 集群的部署过程,任务的启动流程等。

Drawing 2.png

Flink 程序在运行时主要有 TaskManager、JobManager、Client 三种角色。其中 JobManager 扮演着集群中的管理者 Master 的角色,它是整个集群的协调者,负责接收 Flink Job、协调检查点、Failover 故障恢复等,同时管理 Flink 集群中从节点 TaskManager。

TaskManager 是实际负责执行计算的 Worker,在其上执行 Flink Job 的一组 Task,每个 TaskManager 负责管理其所在节点上的资源信息,比如内存、磁盘、网络,在启动的时候将资源的状态向 JobManager 汇报。

Client 是 Flink 程序提交的客户端,当用户提交一个 Flink 程序时,会先创建一个 Client,该 Client 首先会对用户提交的 Flink 程序进行预处理,然后提交到 Flink 集群中处理,所以 Client 需要从用户提交的 Flink 程序配置中获取 JobManager 的地址,并建立到 JobManager 的连接,将 Flink Job 提交给 JobManager。

面试题 7:请谈谈 Flink 中的计算资源 Task Slot。

Flink 中的计算资源是非常容易被忽略的一个知识点,它直接关系着我们线上 Flink 任务调优的原理和过程,变相的考察我们对于大数量下的 Flink 资源分配和调优是否熟悉。

在 Flink 集群中,一个 TaskManger 就是一个 JVM 进程,并且会用独立的线程来执行 Task,为了控制一个 TaskManger 能接受多少个 Task,Flink 提出了 Task Slot 的概念。

我们可以简单地把 Task Slot 理解为 TaskManager 的计算资源子集。假如一个 TaskManager 拥有 5 个 Slot,那么该 TaskManager 的计算资源会被平均分为 5 份,不同的 Task 在不同的 Slot 中执行,避免资源竞争。但需要注意的是,Slot 仅仅用来做内存的隔离,对 CPU 不起作用。那么运行在同一个 JVM 的 Task 可以共享 TCP 连接,以减少网络传输,在一定程度上提高了程序的运行效率,降低了资源消耗。

面试题 8:请谈谈 Flink 中的并行度设置

Flink 使用并行度来定义某一个算子被切分成多少个子任务。我们的 Flink 代码会被转换成逻辑视图,在实际运行时,根据用户的并行度配置会被转换成对应的子任务进行执行。

Flink 本身支持不同级别来设置我们任务并行度的方法,它们分别是:

  • 算子级别

  • 环境级别

  • 客户端级别

  • 集群配置级别

需要特别指出的是,设置并行度的优先级依次是:算子级别 > 环境级别 > 客户端级别 > 集群配置级别。

面试题 9:请谈谈 Flink 支持的集群规模情况。

这个面试题需要我们把生产环境中使用的集群规模、配置情况、Flink 版本等介绍清楚;同时说明部署模式(一般是 Flink on Yarn),除此之外,我们也可以同时在小集群(少于 5 个节点)和拥有 TB 级别状态的上千个节点上运行 Flink 任务。

面试题 10:请谈谈 Flink 中的时间分类。

这道题考察我们开发者对于 Flink 中的时间类型的掌握程度,Flink 中的时间是最基本的概念,我们任何一个实时计算任务都需要进行实践特性的选择。

我们在 “08 | Flink 窗口、时间和水印”课时中提到过 Flink 中的时间分为三种:

  • 事件时间(Event Time),即事件实际发生的时间;

  • 摄入时间(Ingestion Time),事件进入流处理框架的时间;

  • 处理时间(Processing Time),事件被处理的时间。

面试题 11:请谈谈 Flink 中的水印。

Flink 中的水印是难度较高的一个知识点,这个问题考察开发者在实际生产中如何处理乱序问题的,是基于什么样的考虑选择不同的水印生成方式。

水印的出现是为了解决实时计算中的数据乱序问题,它的本质是 DataStream 中一个带有时间戳的元素。如果 Flink 系统中出现了一个 WaterMark T,那么就意味着 EventTime < T 的数据都已经到达,窗口的结束时间和 T 相同的那个窗口被触发进行计算了。

也就是说:水印是 Flink 判断迟到数据的标准,同时也是窗口触发的标记。

Flink 中的水印有两种:

  • 周期生成水印 AssignerWithPeriodicWatermarks,周期默认的时间是 200ms;

  • 按需要生成水印 PunctuatedWatermark,它适用于根据接收到的消息判断是否需要产生水印。

面试题 12:请谈谈 Flink 中的窗口。

这道题考察的是开发者在不同的业务场景中是如何选择时间窗口的,当然变相的就会和你的业务关联,为什么这样选择窗口?他有什么特点?

根据窗口数据划分的不同,目前 Flink 支持如下 3 种:

  • 滚动窗口,窗口数据有固定的大小,窗口中的数据不会叠加;

  • 滑动窗口,窗口数据有固定的大小,并且有生成间隔;

  • 会话窗口,窗口数据没有固定的大小,根据用户传入的参数进行划分,窗口数据无叠加。

总结

本课时主要是 Flink 基础相关的面试题,对应前面的第 01 到 06 课时,你可以根据需要去对应的章节详细查看。另外,建议你要多多阅读对应知识点的源码,做到知其然且知其所以然。


第40讲:Flink 面试-进阶篇

Flink 面试进阶篇主要包含了 Flink 中的数据传输、容错机制、序列化、数据热点、反压等实际生产环境中遇到的问题等考察点。这一阶段主要考察我们对 Flink 掌握的深度,也是给面试官留下好印象的关键环节。

面试题 1:请谈谈你对 Flink Table & SQL 的了解情况?以及 TableEnvironment 这个类有什么样的作用?

这道题考察的是对 Flink Table & SQL 的掌握情况,要知道 Flink 中的 TableEnvironment 有 5 个之多,那么对于 TableEnvironment 的掌握就显得特别重要。

TableEnvironment 是 Table API 和 SQL 集成的核心概念,它主要被用来创建 Table & SQL 程序的上下文执行环境,这个类主要用来:

  • 在内部 catalog 中注册表

  • 注册外部 catalog

  • 执行 SQL 查询

  • 注册用户定义(标量、表或聚合)函数

  • 将 DataStream 或 DataSet 转换为表

  • 持有对 ExecutionEnvironment 或 StreamExecutionEnvironment 的引用

面试题 2:Flink SQL 的原理是什么?请谈谈整个 SQL 的解析过程。

我们在第 05 课时“Flink Table & SQL 编程和案例” 中提过 Flink 把 SQL 的解析、优化和执行教给了 Calcite。

这道题比较深入,我们在使用 Flink Table & SQL 时要知道它的运行原理,才能针对性地做一些调优。

基于此,一次完整的 SQL 解析过程如下图所示:

image (12).png

  • 用户使用对外提供的 Stream SQL 语法来开发业务应用;

  • 用 calcite 对 StreamSQL 进行语法检验,语法检验通过后,转换成 calcite 的逻辑树节点,最终形成 calcite 的逻辑计划;

  • 采用 Flink 自定义的优化规则和 calcite 火山模型、启发式模型共同对逻辑树进行优化,生成最优的 Flink 物理计划;

  • 对物理计划采用 janino codegen 生成代码,生成用低阶 API DataStream 描述的流应用,并提交到 Flink 平台执行。

面试题 3:请谈谈你对 Flink 容错的理解。

Flink 的容错机制是非常重要的一个特性,我们在回答这个问题时,要把 CheckPoint 和 State 都答出来,并且阐述一下原理。

Flink 实现容错主要靠强大的 CheckPoint 和 State 机制。Checkpoint 负责定时制作分布式快照、对程序中的状态进行备份;State 用来存储计算过程中的中间状态。

Flink 提供了三种可用的状态后端用于在不同情况下进行状态后端的保存:

  • MemoryStateBackend

  • FsStateBackend

  • RocksDBStateBackend

面试题 4 :Flink 是如何保证 Exactly-once 语义的

这道题在面试时一定会遇到,Flink 的“精确一次”语义的支持是区别于其他框架最显著的特性之一。

Flink 通过实现两阶段提交和状态保存来实现端到端的一致性语义,分为以下几个步骤:

  • 开始事务(beginTransaction),创建一个临时文件夹,然后把数据写入这个文件夹里面;

  • 预提交(preCommit),将内存中缓存的数据写入文件并关闭;

  • 正式提交(Commit),将之前写完的临时文件放入目标目录下,这代表着最终的数据会有一些延迟;

  • 丢弃(Abort),丢弃临时文件。

我们在第 14 课时“Flink Exactly-once 实现原理解析”中还对 Flink 分布式快照的核心元素 Barrier 和两阶段提交的原理做过详细讲解,可以参考。

面试题 5:请谈谈 Flink 中的内存管理

Flink 的内存管理一般会在面试者与面试官讨论反压问题解决方案时被提及,对于内存管理的准确掌握也是我们进行内存调优和配置的前提。

Flink 并不是将大量对象存在堆上,而是将对象都序列化到一个预分配的内存块上,此外,Flink 大量使用了堆外内存。如果需要处理的数据超出了内存限制,则会将部分数据存储到硬盘上。

Flink 为了直接操作二进制数据实现了自己的序列化框架。

理论上 Flink 的内存管理分为以下 3 部分。

  • Network Buffers:这个是在 TaskManager 启动的时候分配的,这是一组用于缓存网络数据的内存,每个块是 32K,默认分配 2048 个,可以通过“taskmanager.network.numberOfBuffers”修改。

  • Memory Manage pool:大量的 Memory Segment 块,用于运行时的算法(Sort/Join/Shuffle 等),这部分启动时会被分配。根据配置文件中的各种参数来计算内存的分配方法,并且内存的分配支持预分配和 lazy load,默认懒加载的方式。

  • User Code,这个是除了 Memory Manager 之外的内存用于 User Code 和 TaskManager 本身的数据结构。

面试题 6:请谈谈你遇到的数据倾斜问题?Flink 中的 Window 出现了数据倾斜,你有什么解决办法?

这道题也是面试中一定会被提及的问题,数据倾斜是大数据领域最常见的问题之一。Flink 中对于数据倾斜的调优极其重要,我们一定要掌握。

我们在第 16 课时“如何处理生产环境中的数据倾斜问题”中对于这个问题有过一整节的讲解。

产生数据倾斜的原因主要有 2 个方面:

  • 业务上有严重的数据热点,比如滴滴打车的订单数据中北京、上海等几个城市的订单量远远超过其他地区;

  • 技术上大量使用了 KeyBy、GroupBy 等操作,错误的使用了分组 Key,人为产生数据热点。

因此解决问题的思路也很清晰:

  • 业务上要尽量避免热点 key 的设计,例如我们可以把北京、上海等热点城市分成不同的区域,并进行单独处理;

  • 技术上出现热点时,要调整方案打散原来的 key,避免直接聚合;此外 Flink 还提供了大量的功能可以避免数据倾斜。

另外我们还可以结合实际工作中出现的问题做举例说明。

面试题 7:Flink 任务出现很高的延迟,你会如何入手解决类似问题?

这是一个实操性很强的问题,我们在回答这类问题一定要结合实际情况来说。在生产环境中处理这类问题会从以下方面入手:

  • 在 Flink 的后台任务管理中,可以看到 Flink 的哪个算子和 task 出现了反压;

  • 资源调优和算子调优,资源调优即对作业中的 Operator 并发数(Parallelism)、CPU(Core)、堆内存(Heap_memory)等参数进行调优;

  • 作业参数调优,并行度的设置、State 的设置、Checkpoint 的设置。

面试题 8: 请谈谈你们是如何处理脏数据的?

这也是一个开放性的面试题,建议你结合自己的实际业务来谈。比如可以通过一个 fliter 算子将不符合规则的数据过滤出去。当然了,我们也可以在数据源头就将一些不合理的数据抛弃,不允许进入 Flink 系统参与计算。

面试题 9:请谈谈 Operator Chain 这个概念?

算子链是我们进行任务调优一定会遇到的问题,主要考察我们对于概念是否正确理解,实际操作中有怎样的指导作用。

为了更高效地分布式执行,Flink 会尽可能地将 Operator 的 Subtask 链接(Chain)在一起形成 Task,每个 Task 在一个线程中执行。将 Operators 链接成 Task 是非常有效的优化,它能减少:

  • 线程之间的切换;

  • 消息的序列化/反序列化;

  • 数据在缓冲区的交换;

  • 延迟的同时提高整体的吞吐量。

这就是我们所说的算子链

面试题 10:Flink 在什么情况下才会把 Operator Chain 在一起形成算子链?

这道题是有标准答案的,截止 1.11 版本,Flink 的算子之间形成算子链需要以下条件:

  • 上下游的并行度一致

  • 下游节点的入度为 1(即下游节点没有来自其他节点的输入)

  • 上下游节点都在同一个 Slot Group 中

  • 下游节点的 Chain 策略为 ALWAYS(可以与上下游链接,Map、Flatmap、Filter 等默认是 ALWAYS)

  • 上游节点的 Chain 策略为 ALWAYS 或 HEAD(只能与下游链接,不能与上游链接,Source 默认是 HEAD)

  • 两个节点间数据分区方式是 Forward

  • 用户没有禁用 Chain

面试题 11:请谈谈 Flink 中的分布式快照机制是如何实现的?

这道题也是考察我们对于 Flink 掌握深度的一个问题,需要你完全理解 Flink 中的分布式快照机制的实现原理。

Flink 容错机制的核心部分是制作分布式数据流和操作算子状态的一致性快照,这些快照充当一致性 Checkpoint,系统可以在发生故障时回滚。Flink 用于制作这些快照的机制在“分布式数据流的轻量级异步快照”中进行了描述,它受到分布式快照的标准 Chandy-Lamport 算法的启发,专门针对 Flink 的执行模型而定制。

image (13).png

barrier 在数据流源处被注入并行数据流中。快照 n 的 barrier 被插入的位置(我们称为 Sn)是快照所包含的数据在数据源中最大位置。例如,在 Apache Kafka 中,此位置将是分区中最后一条记录的偏移量,将该位置 Sn 报告给 Checkpoint 协调器(Flink 的 JobManager)。

接着 barrier 向下游流动。当一个中间操作算子从其所有输入流中收到快照 n 的 barrier 时,它会为快照 n 发出 barrier 进入其所有输出流中。 一旦 sink 操作算子(流式 DAG 的末端)从其所有输入流接收到 barrier n,它就向 checkpoint 协调器确认快照 n 完成。在所有 sink 确认快照后,意味着快照已完成。

一旦完成快照 n,job 将永远不再向数据源请求 Sn 之前的记录,因为此时这些记录(及其后续记录)将已经通过整个数据流拓扑,也即已经被处理结束。

总结

这一课时我们主要介绍了 Flink 面试中的一些有深度的问题,这些问题是我们在技术面试中能否通过的关键部分,也是考察我们对于 Flink 掌握深度的部分。由于篇幅的原因我们不能 100% 覆盖所有高级进阶的面试题目,建议你参考我之前的文章《全网第一份 | Flink 学习面试灵魂40问,看看你能答上来几个》《Flink 面试通关手册》


第41讲:Flink 面试-源码篇

Flink 的源码篇包含了 Flink 的核心代码实现、Job 提交流程、数据交换、分布式快照机制、Flink SQL 的原理等考察点。你应该记得,我们在前面近 40个课时中几乎每一课时都有一定的篇幅是源码阅读,源码部分的考察是面试时十分重要的一关,如果你对 Flink 的源码有一定的研究而不仅仅停留在使用阶段,那么你的面试成功率将得到大幅提升。

我们本课时将把 Flink 面试中源码部分最高频的考点列举出来。

面试题 1:请从源码层面谈谈 Flink Job 的提交流程。

用户提交的 Flink Job 会被转化成一个 DAG 任务运行。Flink Job 的提交涉及的类主要包括:StreamGraph、JobGraph、ExecutionGraph、TaskManager、JobManager、ResourceManager。

JobManager 会把接收到的需要执行的应用程序进行打包,然后把 JobGraph 转换成可以执行的ExecutionGraph,接着向 ResourceManager 请求执行任务所需要的资源,也就是我们之前课程中提到的 Slot,如果资源获取成功 JobManager 会负责所有的任务调度,比如 Checkpoint,并且将任务派发给 TaskManager 去执行。

面试题 2:我们通常说的 Flink 的“三层图”结构是什么意思?

这道题要求面试者掌握Flink 框架引擎划分执行计划的详细过程。

一个 Flink 任务的 DAG 生成计算图大致经历以下3个过程。

  • 首先,StreamGraph 的拓扑结构最接近代码层面,主要由 StreamNode 和 StreamEdge 构成,其中 StreamNode 对应着 Operator,它们通过 StreamEdge 进行链接。

  • 其次,JobGraph 是能被 Flink 引擎识别的数据结构,由JobVertex、JobEdge和 IntermediateDataSet3个元素组成。我们可以把JobGraph 形象地比喻为一个抽水系统,JobVertex 是水泵,JobEdge 是水管,而 IntermediateDataSet 则是中间的蓄水池。

  • 最后,ExecutionGraph 由 JobGraph 转换而来,包含了任务具体执行所需的内容,是最贴近底层实现的执行图。

image (21).png

上图清晰展现了 Flink 各个图之间的转换过程和工作原理。

面试题 3:请从源码层面谈谈 JobManger 在集群中扮演了什么角色?

我们在第03课时“Flink 的编程模型与其他框架比较” 中专门用了一小节的内容来讲解 Flink 中的角色和作用,其中 JobManager 是 Flink 集群中非常重要的一个角色。

JobManager 负责整个 Flink 集群任务的调度及资源的管理,从客户端中获取提交的应用,然后根据集群中 TaskManager 上 TaskSlot 的使用情况,为提交的应用分配相应的 TaskSlot 资源并命令 TaskManager 启动从客户端中获取的应用。

JobManager 相当于整个集群的 Master 节点,且整个集群有且只有一个活跃的 JobManager,负责整个集群的任务管理和资源管理。

JobManager 和 TaskManager 之间通过 Actor System 进行通信,获取任务执行的情况并通过 Actor System 将应用的任务执行情况发送给客户端。

同时在任务执行的过程中,Flink JobManager 会触发 Checkpoint 操作,每个 TaskManager 节点收到 Checkpoint 触发指令后,完成 Checkpoint 操作,所有的 Checkpoint 协调过程都是在 Fink JobManager 中完成。

当任务完成后,Flink 会将任务执行的信息反馈给客户端,并且释放掉 TaskManager 中的资源以供下一次提交任务使用。

面试题 4:JobManger 在集群启动过程中起到什么作用?

一定要注意,这道题目和面试题 3 有一定的相似性,但是这里会要求我们从源码层面介绍 JobManager 在启动过程中涉及的主要类和方法。

首先,我们要回答出 JobManager 的主要职责,主要包括负责整个 Flink 集群任务调度和资源的管理,并且负责接收 Flink 作业、调度 Task、收集作业状态和管理 TaskManager。

然后,如果开发者能从源码层面回答出涉及的关键方法,会大大增加面试官的印象。

  • RegisterTaskManager:它由想要注册到 JobManager 的 TaskManager 发送,注册成功则通过 AcknowledgeRegistration 消息进行 Ack。

  • SubmitJob:将 Job 提交给 Client,提交的信息是 JobGraph 形式的作业描述信息。

  • CancelJob:请求取消指定ID的作业,成功会返回 CancellationSuccess,否则返回 CancellationFailure。

  • UpdateTaskExecutionState:由 TaskManager 发送,用来更新执行节点(ExecutionVertex)的状态;成功则返回 true,否则返回 false。

  • RequestNextInputSplit:TaskManager 上的 Task 请求下一个输入 split,成功则返回 NextInputSplit,否则返回 null。

  • JobStatusChanged:它意味着作业的状态(RUNNING、CANCELING、FINISHED等)发生变化,这个消息由 ExecutionGraph 发送。

面试题 5:TaskManager 在集群中扮演了什么角色?

这道题和面试题 3 类似,TaskManager 是集群中的 Worker 角色,我们在第 03 课时“Flink 的编程模型与其他框架比较”中也对 TaskManager 做过详细讲解。

TaskManager 相当于整个集群的 Slave 节点,负责具体的任务执行和对应任务在每个节点上的资源申请和管理。

客户端通过将编写好的 Flink 应用编译打包,提交到 JobManager,然后 JobManager 会根据已注册在 JobManager 中 TaskManager 的资源情况,将任务分配给有资源的 TaskManager 节点,然后启动并运行任务。

TaskManager 从 JobManager 接收需要部署的任务,然后使用 Slot 资源启动 Task,建立数据接入的网络连接,接收数据并开始数据处理。同时 TaskManager 之间的数据交互都是通过数据流的方式进行的。

可以看出,Flink 的任务运行其实是采用多线程的方式,这和 MapReduce 多 JVM 并行的方式有很大的区别,Flink 能够极大提高 CPU 使用效率,在多个任务和 Task 之间通过 TaskSlot 方式共享系统资源,每个 TaskManager 中通过管理多个 TaskSlot 资源池对资源进行有效管理。

面试题 6:TaskManger 的启动过程是怎样的?

相比 JobManager而言,TaskManager 的启动流程较为简单,启动类入口为org.apache.flink.runtime.taskexecutor.TaskManagerRunner。核心的入口如下所示:

public static void runTaskManager(Configuration configuration, ResourceID resourceId) throws Exception {
        //主要初始化一些service,并新建一个TaskExecutor
		final TaskManagerRunner taskManagerRunner = new TaskManagerRunner(configuration,resourceId);
		//调用TaskExecutor的start()方法
        taskManagerRunner.start();
}

启动过程中主要进行 Slot 资源的分配、RPC 服务的初始化,以及JobManager 进行通信等。

面试题 7:Flink 计算资源的调度是如何实现的?

这类问题的难度都非常高,考察开发人员在进行资源配置和调优的过程中是否对源码有足够的了解。我们在第 17 课时“生产环境中的并行度和资源配置”中对 Flink 中的资源有过详细讲解。

TaskManager 中最细粒度的资源是 Task slot,代表了一个固定大小的资源子集,每个 TaskManager 会将其所占有的资源平分给它的 slot。

通过调整 task slot 的数量,用户可以定义 task 之间是如何相互隔离的。每个 TaskManager 有一个 slot,也就意味着每个 task 运行在独立的 JVM 中;每个 TaskManager中有多个 slot 的话,也就意味着多个 task 运行在同一个 JVM 中。

而在同一个 JVM 进程中的 task,可以共享 TCP 连接(基于多路复用)和心跳消息,可以减少数据的网络传输,也能共享一些数据结构,在一定程度上减少了每个 task 的消耗。 每个 slot 可以接受单个 task,也可以接受多个连续 task 组成的 pipeline,如下图所示。FlatMap 函数占用一个 taskslot,而 key Agg 函数和 sink 函数共用一个 taskslot:

image (22).png

面试题 8:请你谈谈 Flink 的数据抽象及数据交换过程?

这个问题涉及 Flink 中的内存设计和定义,需要你将核心的类答出来。

我们知道 JVM 在对象序列化上有一些固有的缺陷,主要体现在存储对象的密度较低,含有大量不需要的信息,并且 FGC 还会对整体的吞吐和响应有严重影响。

为了降低这些影响,Flink 实现了自己的内存管理。主要体现在,Flink 定义了自己的内存抽象:MemorySegment。

public abstract class MemorySegment {
    protected static final Unsafe UNSAFE;
    protected static final long BYTE_ARRAY_BASE_OFFSET;
    private static final boolean LITTLE_ENDIAN;
    protected byte[] heapMemory;
    protected long address;
    protected long addressLimit;
    protected int size;
    protected Object owner;
    MemorySegment(byte[] buffer, Object owner) {
        if (buffer == null) {
            throw new NullPointerException("buffer");
        } else {
            this.heapMemory = buffer;
            this.address = BYTE_ARRAY_BASE_OFFSET;
            this.size = buffer.length;
            this.addressLimit = this.address + (long)this.size;
            this.owner = owner;
        }
    }
    ...

我们可以把MemorySegment 看作是一个 32KB大的内存块的抽象,这块内存既可以是 JVM 里的一个 byte[],也可以是堆外内存(DirectByteBuffer)。

在 MemorySegment 这个抽象之上,Flink 抽象出了两个关键的进行数据转换的类:

  • Buffer,用于各个 TaskManager 进行数据传输;

  • StreamRecord,用于 Java 对象和 Buffer 对象互相转换。

面试题9:谈谈 Flink 的 SQL 部分是如何实现的?

Table SQL 是 Flink 提供的高级 API 操作。Flink SQL 是 Flink 实时计算为简化计算模型,降低用户使用实时计算门槛而设计的一套符合标准 SQL 语义的开发语言。

我们在第 5 课时“Flink Table & SQL 编程和案例”中进行过非常详细的讲解。

Flink 把 SQL 的解析、优化和执行教给了Calcite。从图中可以看到,无论是批查询 SQL 还是流式查询 SQL,都会经过对应的转换器 Parser 转换成为节点树 SQLNode tree,然后生成逻辑执行计划 Logical Plan,逻辑执行计划在经过优化后生成真正可以执行的物理执行计划,交给 DataSet 或者 DataStream 的 API 去执行。

image (23).png

![在这里插入图片描述](https://img-blog.csdnimg.cn/f395dc28550148c2bd88fdeed3f58acf.png#pic_center)

上图清晰地展示了 SQL 的整个解析和转换过程,当 SQL 被转换为可以执行的物理执行计划后会被分发到各个 TaskManager 节点中去,并且最后翻译成代码运行。

总结

这一课时我们介绍了 Flink 源码面试中的一些经典题目,在之前的课程中都会花一定的篇幅去介绍源码和实现。可以这么说,源码的阅读决定了我们是否真正掌握了一个框架,建议你在学习 Flink 的每个模块时都要养成阅读源码的习惯。另外,抽空也可以参考我之前的面试相关文章《全网第一份 | Flink学习面试灵魂40问,看看你能答上来几个》《Flink面试通关手册》


第42讲:Flink 面试-方案设计篇

Flink 的方案设计面试题目在面试中,是面试官了解我们项目的最直接的问题,它通常体现在面试者回答自己的项目整体是如何设计的?Flink 在你的项目中起到什么作用?有没有在应用过程中对 Flink 有一些定制开发等。

如何介绍自己的项目,为什么技术选型 Flink 也代表我们对于 Flink 框架的了解程度,我们本课时将介绍 Flink 典型的应用场景和整体的方案设计。

面试题1:基于 Flink 的实时数据仓库是如何做的?

我们在第 01 课时“Flink 的应用场景和架构模型”和第 21 课时“Flink 在实时计算平台和实时数据仓库中的应用”中对基于 Flink 的实时数仓做过详细介绍。

在回答这类问题时,我们要从 Flink 的优势开始入手,介绍基于 Flink 的实时数仓建设的关键技术选型和整体设计。

传统的离线数据仓库将业务数据集中进行存储后,以固定的计算逻辑定时进行ETL和其他建模后产出报表等应用。离线数据仓库主要是构建 T+1 的离线数据,通过定时任务每天拉取增量数据,然后创建各个业务相关的主题维度数据,对外提供 T+1 的数据查询接口。计算和数据的实时性均较差,业务人员无法根据自己的即时性需要获取几分钟之前的实时数据。数据本身的价值随着时间的流逝会逐步减弱,因此数据发生后必须尽快地达到用户的手中,实时数仓的构建需求也应运而生。

总之就是一句话:时效性的要求。

Flink 在实时数仓和实时 ETL 中有天然的优势:

  • 状态管理,实时数仓里面会进行很多的聚合计算,这些都需要对状态进行访问和管理,Flink 支持强大的状态管理;

  • 丰富的 API,Flink 提供了极为丰富的多层次 API,包括 Stream API、Table API 及 Flink SQL;

  • 生态完善,实时数仓的用途广泛,Flink 支持多种存储(HDFS、ES 等);

  • 批流一体,Flink 已经在将流计算和批计算的 API 进行统一。

我们在进行实时数仓的设计时,一般也是分为 ODS 源数据接入层、DWD 明细层、DWS 汇总层、ADM 应用层。

这其中比较关键的技术点:实时数仓的明细层的汇总一般是基于 Flink 等接入 Kafka 消息进行关联的,维度表的数据一般会放在 HDFS、HBase 中作为明细层的补充。另外,在实时数据仓库中要选择不同的 OLAP 库来满足即席查询。OLAP 数据库的选择至关重要,你可以参考我之前写的文章《你需要的不是实时数仓 | 你需要的是一款强大的OLAP数据库》。

此外,我们在和面试官交流的过程中,可以将自己的实时数据的架构图完整画出来,这样会给人很深刻的印象,你可以参考下面两张架构设计图。

Drawing 0.png

网易严选的实时数据仓库设计图

Drawing 1.png

美团的实时数仓分层架构模型图

面试题2:基于 Flink 的实时计算平台是如何做的?

实时计算平台的搭建是随着越来越多的业务场景需要实时计算而产生的。由于离线计算天然时效性不强,一般都是隔天级别的滞后,业务数据随着实践的推移,本身的价值就会逐渐减少。

我们在第 03 课时“Flink 的编程模型与其他框架比较”中,提到过 Flink 自身独有的优势。由于 Flink 在架构、容错、反压上表现出来的优势和特性,使得 Flink 在实时计算平台的搭建上占有一席之地。

我们在第 21 课时“Flink 在实时计算平台和实时数据仓库中的应用”中提到过一般的实时计算平台的构成大都是由以下几部分构成。

  • 实时数据收集层

在实际业务中,大量的实时计算都是基于消息系统进行的数据收集和投递,这都离不开强大的消息中间件。目前业界使用最广的是 Kafka,另外一些重要的业务数据还会用到其他消息系统比如 RocketMQ 等。Kafka 因为高吞吐、低延迟的特性,特别适合大数量量、高 QPS 下的业务场景,而 RocketMQ 则在事务消息、一致性上有独特的优势。

  • 实时计算层

Flink 在计算层同时支持流式及批量分析应用,这就是我们所说的批流一体,Flink 承担了数据的实时采集实时计算下游发送的角色。随着 Blink 的开源和一些其他实时产品的开源,支持可视化、SQL 化的开发模式已经越来越普及。

  • 数据存储层

这里是我们的实时数据存储层,存储层除了传统 MySQL 等存储引擎以外,还会根据场景数据的不同存储在 Redis、HBase、OLAP 中。而这一层我个人认为最重要的技术选型则是 OLAP。OLAP 的技术选型直接制约着数据存储层和数据服务层的能力。关于 OLAP 的技术选型,可以参考这里

  • 数据服务层

数据服务层会提供统一的对外查询、多维度的实时汇总,加上完善的租户和权限设计,能够支持多部门、多业务的数据需求。另外,基于数据服务层还会有数据的展示、大屏、指标可视化等。

我们在回答这个面试问题时,可以结合自己的实际项目回答,例如,在实时数据收集层中的技术选型是什么、支持了多大的数据量以及取得的业务成果;并且可以把自己的架构图完整地画出来。你也可以参考下面的架构图来画出自己的整体架构图。

Drawing 2.png

美团的实时计算平台图

Drawing 3.png

微博的实时计算平台图

面试题3:有没有做过基于 Flink SQL 的计算平台?你有什么思路?

基于 Flink SQL 的实时计算平台是很多大公司提高开发效率、降低开发成本、降低维护成本作出的选择。一般的 SQL 开发平台都会有以下几个模块:

  • SQL 开发和提交模块

  • 完善的权限管理体系

  • UDF 管理模块

  • 资源调度模块

  • 日志和监控模块

这其中,SQL 的开发和提交是核心,成熟的 SQL 开发平台应该是和公司常用的组件栈打通,基于 Flink 原生的 SQL 模块支持更为丰富的 Source 和 Sink。并且支持丰富的作业配置,如作业 Checkpoint、重启策略等。

权限管理模块中,我们的 SQL 应该在作业级别进行多租户的权限管控,对于原表和目标表更应该精确到开发者级别。

UDF 模块应该支持用户自定义基于业务的复杂 UDF,并且可以快捷方便地更新版本。

资源和调度模块可以支持算子级别的并行度和内存设置,并且应该支持作业在不同集群间进行切换。

日志和监控模块中是我们进行作业调优、异常监控非常重要的模块,我们应该有专门的服务进行日志收集和查询,异常监控方面可以做到指定到人且不同渠道(邮件、电话、钉钉等)的报警。

总结

本课时我们讲解了 Flink 面试中非常重要的一个模块:方案设计篇。本文介绍了 Flink 在实时数据仓库、实时计算平台、SQL 平台三种业务场景中的方案设计,大家在面试的过程中要结合实际的业务背景进行讲解。


结束语:疾风亦有归途

当你看到这篇文章的时候,恭喜你,你已经学完了本课程的所有内容。

有一类事情看起来枯燥无味乏善可陈,做起来巨难无比,写作就是其中之一,回忆起这几个月漫长且短暂的写作旅途,感慨颇多。我本身是数据方向的开发者之一,同样是从最简单的 Hadoop WordCount 入门,做过数据领域最脏最累的活,也做过看起来高大上的工作。

仅仅就实时计算领域,这几年的发展速度令人惊奇,比如我接触过的 Samza、S4、Heron、Storm 等,它们都曾经在各自的时代风头无两,在自己擅长的业务领域所向披靡。但是随着业务和技术思想的不断更新迭代,最终出现了 Spark、Flink 这样优秀的框架。

如果你是数据领域的一名开发者,或者是一个即将走出校门进入这个行业的初学者,那么你一定有这样的困惑,大数据领域的开源框架浩如烟海,每年仅仅进入 Apache 的开源项目就多达数十个。我作为开发者,同样也曾经是面试官,遇到过很多同学有过这样的问题:熟悉或者了解大量的开发框架,讲起名词来滔滔不绝,但是深入交流才发现,对于原理的掌握过于浅薄,导致面试失败。这是实时计算乃至数据领域最好的时代,遇到 Spark、Flink 这样优秀的框架,阅读源码是必不可少的一部分,所谓知其然且知其所以然。

还有很多很多的读者私信问我,为什么你不用 Scala 开发?为什么不用 Python 来实现?语言之争向来是开发圈子经久不衰的话题。Flink 作为一个优秀的框架,大部分基于 Java 开发,那么就选择 Java 语言好了。如果你所在的小组或者公司对 Scala 推崇备至,那么就用 Scala 好了。这些都不重要,重要的是开发前的业务调研、详细设计等,代码的实现占比是很小的。

对于刚刚接触 Flink 或者刚刚接触实时计算的同学们来说,你肯定会经历一段非常难熬的日子。我曾经也有过一段这样的经历,白天啃公司的工程和业务,晚上和周末啃买的书,数不清熬了多少个深夜,但这也恰恰是你成长最快的时候,这段难熬的日子也是你夯实基础、快速升级的必经之路。

就像我之前在个人的公众号上写的一样。学习嘛,说到底就是为了掌握技能赚钱,你可以选择糊弄,做不到 100 分做到 60、70 分就可以了;你也可以选择努力一把,迅速成长,凡事做到 100 分,为后面漫长的职业生涯打下基础,等技术能力达到一个层次,跳出这个小圈子,可以去做技术创业或者商业相关的东西,后面的路会更宽。

我选择的是后者。

如果你是像我上面那么做的话,工作超过一年多的时候就会发现,开发本身是工作中最最简单的工作内容。你面对的是需求讨论、架构设计、投入产出比、跨部门推进工作,还有可能在多方合作中找到利益共同点为自己服务,除去技术本身的商业嗅觉等。

我还是那句话,技术本身都是雕虫小技

《士兵突击》中,许三多是个“在卑微中伟大”的赤子,他“明明是个强人”却“天生是个熊样”。他很简单,却活得精彩、有意义,因为他懂得珍惜机会。

就像高连长说的:“他对每一件小事,就像救命的稻草一样抓着。有一天我一看,好家伙,他抱着的已经是一棵参天大树了。”

希望每个读者,最后怀抱的都是参天大树。

专栏体会

这个专栏是我结合着实际工作中的实践写出来的,包含了大量的在大数据量下的实践经历,是一门可以带你完全掌握 Flink 核心知识点的课程,也可以对你在实际开发中起到一定的指导作用。Flink 还在不断地更新迭代,仅就目前来看,在实时计算领域 Flink 的发展道阻且长,但是前途光明。

最后,如果你是一名刚刚进入大数据开发领域在学习实时计算相关的技术,那么不妨从 Flink 入手,从这门课入手。如果你是公司数据方向的技术带头人或者 CTO,那么不妨在实际生产中尝试使用 Flink,相信 Flink 一定不会让你失望的。


  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

办公模板库 素材蛙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值