Flink常见面试题总结

文章目录

  • [1. 简单介绍一下Flink](#1. 简单介绍一下Flink)
  • [2. Flink 的运行必须依赖Hadoop组件吗?](#2. Flink 的运行必须依赖Hadoop组件吗?)
  • [3. Flink 和 Spark Streaming 的区别?](#3. Flink 和 Spark Streaming 的区别?)
  • [4. Flink集群角色](#4. Flink集群角色)
  • [5. Flink核心概念](#5. Flink核心概念)
    • [5.1 并行度](#5.1 并行度)
    • [5.2 算子链(Operator Chain)](#5.2 算子链(Operator Chain))
    • [5.3 任务槽(Task Slots)](#5.3 任务槽(Task Slots))
    • [5.4 任务槽和并行度的关系](#5.4 任务槽和并行度的关系)
  • [6. Flink 的部署模式及区别?](#6. Flink 的部署模式及区别?)
    • [6.1 会话模式](#6.1 会话模式)
    • [6.2 单作业模式(Per-Job Mode)](#6.2 单作业模式(Per-Job Mode))
    • [6.3 应用模式(Application Mode)](#6.3 应用模式(Application Mode))
    • [6.4 具体运行模式的部署](#6.4 具体运行模式的部署)
  • [7. 逻辑流图/作业图/执行图/物理流图](#7. 逻辑流图/作业图/执行图/物理流图)
  • [8. Yarn 应用模式作业提交流程](#8. Yarn 应用模式作业提交流程)
  • [9. Flink 的三种时间语义](#9. Flink 的三种时间语义)

Flink 是一个面向流处理和批处理的分布式数据计算引擎,能够基于同一个Flink运行,可以提供流处理和批处理两种类型的功能。 在 Flink 的世界观中,一切都是由流组成的,离线数据是有界的流;实时数据是一个没有界限的流:这就是所谓的有界流和无界流。

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

  1. Spark以批处理为根本
    • Spark数据模型:Spark 采用RDD 模型,Spark Streaming 的DStream实际上也就是一组组小批数据RDD 的集合
    • Spark运行时架构:Spark 是批计算,将DAG 划分为不同的stage,一个完成后才可以计算下一个
  2. Flink以流处理为根本
    • Flink数据模型:Flink 基本数据模型是数据流,以及事件(Event)序列
    • Flink运行时架构:Flink 是标准的流执行模式,一个事件在一个节点处理完后可以直接发往下一个节点进行处理
  3. 架构模型不同
    • Spark Streaming 在运行时的主要角色包括:Master、Worker、Driver、Executor
    • Flink 在运行时主要包含:Jobmanager、Taskmanager 和 Slot
  4. 时间机制
    • Spark Streaming 支持的时间机制有限,只支持处理时间。
    • Flink 支持了流处理程序在时间上的三个定义:处理时间、事件时间、注入时间。

4. Flink集群角色

  • 客户端(Client):代码由客户端获取并做转换,之后提交给JobManager
  • JobManager:就是Flink集群里的"管事人",对作业进行中央调度管理;而它获取到要执行的作业后,会进一步处理转换,然后分发任务给众多的TaskManager。
  • TaskManager :就是真正"干活的人",数据的处理操作都是它们来做的。

5. Flink核心概念

5.1 并行度

  1. 并行子任务和并行度

一个算子任务就被拆分成了多个并行的"子任务"(subtasks),再将它们分发到不同节点,就真正实现了并行计算。

在 Flink 执行过程中,每一个算子(operator)可以包含一个或多个子任务(operator subtask),这些子任务在不同的线程、不同的物理机或不同的容器中完全独立地执行。

一个特定算子的子任务(subtask)的个数 被称之为其并行度 (parallelism)。这样,包含并行子任务的数据流,就是并行数据流 ,它需要多个分区(stream partition)来分配并行任务。一般情况下,一个流程序的并行度 ,可以认为就是其所有算子中最大的并行度。一个程序中,不同的算子可能具有不同的并行度。

例如:如上图所示,当前数据流中有source、map、window、sink四个算子,其中sink算子的并行度为1,其他算子的并行度都为2。所以这段流处理程序的并行度就是2。

  1. 并行度的设置

在Flink中,可以用不同的方法来设置并行度,它们的有效范围和优先级别也是不同的。

设置并行度有多种方式,优先级:算子 > 全局Env> 命令行 > 配置文件

四种方式:

  • 算子中设置
    我们在代码中,可以很简单地在算子后跟着调用setParallelism()方法,来设置当前算子的并行度:
    stream.map(word -> Tuple2.of(word, 1L)).setParallelism(2);
    这种方式设置的并行度,只针对当前算子有效。
  • 全局Env
    我们也可以直接调用执行环境的setParallelism()方法,全局设定并行度:
    env.setParallelism(2);
    这样代码中所有算子,默认的并行度就都为 2了。我们一般不会在程序中设置全局并行度,因为如果在程序中对全局并行度进行硬编码,会导致无法动态扩容。
  • 命令行设置
    在使用 flink run 命令提交应用时,可以增加-p 参数来指定当前应用程序执行的并行度,它的作用类似于执行环境的全局设置:
    bin/flink run --p 2 --c com.atguigu.wc.SocketStreamWordCount ./FlinkTutorial-1.0-SNAPSHOT.jar
  • 配置文件中设置
    我们还可以直接在集群的配置文件flink-conf.yaml中直接更改默认并行度:
    parallelism.default: 2
    这个设置对于整个集群上提交的所有作业有效,初始值为 1。无论在代码中设置、还是提交时的-p 参数,都不是必须的;所以在没有指定并行度的时候,就会采用配置文件中的集群默认并行度。在开发环境中,没有配置文件,默认并行度就是当前机器的CPU核心数。

5.2 算子链(Operator Chain)

  1. 算子间的数据传输

    一个数据流在算子之间传输数据的形式可以是一对一(one-to-one)的直通(forwarding)
    模式
    ,也可以是打乱的重分区(redistributing)模式,具体是哪一种形式,取决于算子的种类。
  • 一对一(One-to-one,forwarding)

    这种模式下,数据流维护着分区以及元素的顺序。比如图中的source和map算子,source算子读取数据之后,可以直接发送给 map算子做处理,它们之间不需要重新分区 ,也不需要调整数据的顺序 。这就意味着map 算子的子任务,看到的元素个数和顺序跟source 算子的子任务产生的完全一样,保证着"一对一"的关系。map、filter、flatMap 等算子都是这种 one-to-one的对应关系 。这种关系类似于Spark中的窄依赖

  • 重分区(Redistributing)

    在这种模式下,数据流的分区会发生改变。比如图中的map和后面的keyBy/window算子之间,以及keyBy/window算子和Sink算子之间,都是这样的关系。

    每一个算子的子任务,会根据数据传输的策略,把数据发送到不同的下游目标任务 。这些传输方式都会引起重分区的过程,这一过程类似于Spark中的shuffle

  1. 合并算子链

    在Flink中,并行度相同的一对一(one to one)算子操作,可以直接链接在一起形成一个
    "大"的任务(task)
    ,这样原来的算子就成为了真正任务里的一部分,如下图所示。每个

    task 会被一个线程执行。这样的技术被称为"算子链 "( Operator Chain)。

    上图中Source和map之间满足了算子链的要求,所以可以直接合并在一起,形成了一个任务;因为并行度为 2,所以合并后的任务也有两个并行子任务。这样,这个数据流图所表示的作业最终会有5个任务,由5个线程并行执行。

    将算子链接成 task 是非常有效的优化:可以减少线程之间的切换和基于缓存区的数据交换,在减少时延的同时提升吞吐量。

5.3 任务槽(Task Slots)

  1. 任务槽(Task Slots)

    Flink 中每一个TaskManager都是一个JVM进程,它可以启动多个独立的线程,来并行执行多个子任务(subtask)。

    很显然,TaskManager 的计算资源是有限的,并行的任务越多,每个线程的资源就会越少。那一个 TaskManager 到底能并行处理多少个任务呢?为了控制并发量,我们需要在TaskManager 上对每个任务运行所占用的资源做出明确的划分,这就是所谓的任务槽(task slots)。

    每个任务槽(task slot)用来独立执行一个子任务的。

    假如一个TaskManager有三个slot,那么它会将管理的内存平均分成三份,每个slot独自占据一份。这样一来,我们在slot上执行一个子任务时,相当于划定了一块内存"专款专用",就不需要跟来自其他作业的任务去竞争内存资源了

    所以现在我们只要2个TaskManager ,就可以并行处理分配好的5个任务 了。

  2. 任务槽数量的设置

    在Flink的/opt/module/flink-1.17.0/conf/flink-conf.yaml配置文件中,可以设置TaskManager

    的slot数量,默认是1个slot。
    taskmanager.numberOfTaskSlots: 8

    需要注意的是,slot 目前仅仅用来隔离内存,不会涉及 CPU的隔离 。在具体应用时,可以将slot数量配置为机器的CPU核心数,尽量避免不同任务之间对CPU的竞争。这也是开发环境默认并行度设为机器CPU数量的原因。

  3. 任务对任务槽的共享

    默认情况下,Flink是允许子任务共享slot的。如果我们保持sink任务并行度为1不变,而作业提交时设置全局并行度为6,那么前两个任务节点就会各自有6个并行子任务,整个流处理程序则有13个子任务。如上图所示,只要属于同一个作业 ,那么对于不同任务节点(算子)的并行子任务,就可以放到同一个slot上执行 。所以对于第一个任务节点source→map,它的6个并行子任务必须分到不同的slot上,而第二个任务节点keyBy/window/apply的并行子任务却可以和第一个任务节点共享slot。

    当我们将资源密集型和非密集型的任务同时放到一个 slot 中,它们就可以自行分配对资源占用的比例,从而保证最重的活平均分配给所有的TaskManager。

    slot 共享另一个好处就是允许我们保存完整的作业管道。这样一来,即使某个TaskManager出现故障宕机,其他节点也可以完全不受影响,作业的任务可以继续执行。

5.4 任务槽和并行度的关系

  • 任务槽是静态的概念,是指 TaskManager 具有的并发执行能力
  • 并行度是动态的概念,也就是 TaskManager运行程序时实际使用的并发能力

整个流处理程序的并行度,就应该是所有算子并行度中最大的那个,这代表了运行程序需要slot数量。

设置合适的并行度能提高运算效率,太多太少都不合适。

怎样设置并行度效率最高呢?

当然是需要把所有的slot都利用起来。考虑到slot共享,我们可以直接把并行度设置为9,这样所有27个任务就会完全占用9个slot。这是当前集群资源下能执行的最大并行度,计算资源得到了充分的利用。

Flink 为各种场景提供了不同的部署模式,主要有以下三种:会话模式(Session Mode)单作业模式(Per-Job Mode)应用模式(Application Mode)

它们的区别主要在于:集群的生命周期 以及资源的分配方式 ;以及应用的main方法到底
在哪里执行
------客户端(Client)还是JobManager。

6.1 会话模式

会话模式其实最符合常规思维。我们需要先启动一个集群,保持一个会话 ,在这个会话中通过客

户端提交作业。集群启动时所有资源就都已经确定,所以所有提交的作业会竞争集群中的资源

6.2 单作业模式(Per-Job Mode)

会话模式因为资源共享会导致很多问题,所以为了更好地隔离资源,我们可以考虑为每个提交的
作业启动一个集群
,这就是所谓的单作业(Per-Job)模式

作业完成后,集群就会关闭,所有资源也会释放。

这些特性使得单作业模式在生产环境运行更加稳定,所以是实际应用的首选模式

需要注意的是,Flink本身无法直接这样运行,所以单作业模式一般需要借助一些资源管理框架来启动集群,比如YARN、Kubernetes(K8S)。

6.3 应用模式(Application Mode)

前面提到的两种模式下,应用代码都是在客户端上执行 ,然后由客户端提交给JobManager的。但是这种方式客户端需要占用大量网络带宽 ,去下载依赖和把二进制数据发送给JobManager;加上很多情况下我们提交作业用的是同一个客户端,就会加重客户端所在节点的资源消耗

所以解决办法就是,我们不要客户端了直接把应用提交到JobManger上运行 。而这也就代表着,我们需要为每一个提交的应用单独启动一个JobManager,也就是创建一个集群。这个JobManager只为执行这一个应用而存在执行结束之后JobManager也就关闭了 ,这就是所谓的应用模式

应用模式与单作业模式,都是提交作业之后才创建集群;单作业模式是通过客户端来提交的,客户端解析出的每一个作业对应一个集群;而应用模式下,是直接由JobManager执行应用程序的

6.4 具体运行模式的部署

  1. Standalone运行模式
    Flink 作业在一个专门的 Flink集群上运行,独立模式不依赖于其他集群管理器(Yarn或者Kubernetes)
  2. Yarn运行模式
  • Session:共享资源,一套集群多个job
  • Per-job:独享资源,代码解析在Client
  • Application:独享资源,代码解析在JobMaster
  1. K8s运行模式(了解)

    支持云原生,未来的趋势

    容器化部署是如今业界流行的一项技术,基于Docker镜像运行能够让用户更加方便地对应用进行管理和运维。容器管理工具中最为流行的就是Kubernetes(k8s),而 Flink也在最近的版本中支持了k8s部署模式。基本原理与YARN是类似的

7. 逻辑流图/作业图/执行图/物理流图

逻辑流图(StreamGraph)→ 作业图(JobGraph)→ 执行图(ExecutionGraph)→ 物理图(Physical Graph)

8. Yarn 应用模式作业提交流程

  • 事件时间EventTime:是事件创建的时间。数据本身携带的时间。
  • 进入时间Ingestion Time:是数据进入Flink的时间。
  • 处理时间ProcessingTime:是每一个执行基于时间操作的算子的本地系统时间,与机器相关,默认的时间属性就是ProcessingTime。

在实际应用中,事件时间语义会更为常见。一般情况下,业务日志数据中都会记录数据生成的时间戳(timestamp),它就可以作为事件时间的判断基础。Flink已经将事件时间作为默认的时间语义了。

相关推荐
Data 3172 小时前
Hive数仓操作(十一)
大数据·数据库·数据仓库·hive·hadoop
qtj-0013 小时前
普通人在刚开始做副业时要注意哪些细节?
大数据·微信·新媒体运营·创业创新
知识分享小能手3 小时前
mysql学习教程,从入门到精通,SQL 修改表(ALTER TABLE 语句)(29)
大数据·开发语言·数据库·sql·学习·mysql·数据分析
a6953188_3 小时前
如何评估一个副业项目的可行性?
大数据·微信·创业创新
州周4 小时前
Flink一点整理
大数据·flink
柚乐果果4 小时前
数据分析实战简例
java·大数据·python
Data 3174 小时前
Hive数仓操作(九)
大数据·数据仓库·hive·hadoop
丶21365 小时前
【大数据】Elasticsearch 实战应用总结
大数据·elasticsearch·搜索引擎
闲人编程5 小时前
elasticsearch实战应用
大数据·python·elasticsearch·实战应用
Data 3178 小时前
Hive数仓操作(三)
大数据·数据库·数据仓库·hive·hadoop