Flink常见面试题总结

文章目录

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

1. 简单介绍一下Flink

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

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

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

3. Flink 和 Spark Streaming 的区别?

  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。这是当前集群资源下能执行的最大并行度,计算资源得到了充分的利用。

6. Flink 的部署模式及区别?

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 应用模式作业提交流程

在这里插入图片描述

9. Flink 的三种时间语义

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/14094.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

掌握Go语言中的net/http包:编写高性能Web服务

掌握Go语言中的net/http包:编写高性能Web服务 引言HTTP服务器构建基础服务器设置路由与处理函数中间件使用高级配置(如TLS/SSL) HTTP客户端开发创建与使用HTTP客户端处理响应 高级客户端特性 处理JSON与表单数据接收与解析JSON接收与解析表单…

实现一个自定义 hook,用于强制刷新当前组件

写在前面 在 react 中,如果 state 数据发生变化,我们知道,会重新渲染该组件。 但是这个前提是我们需要依赖 state 数据的变化,那比如我们并不想定义 state,又或者说我们的操作不能引起 state 的变化,此时…

无人机行业招投标技术详解

一、招标流程与原则 无人机行业的招投标流程通常包括招标公告发布、招标文件购买与审查、投标单位资格预审、投标书编制与递交、开标评标、中标公示与合同签订等步骤。在此过程中,必须遵循公开、公平、公正的原则,确保所有符合要求的投标单位都能获得平…

SpringBoot Bean

配置优先级 Bean的管理 从IOC容器中获取Bean对象:注入IOC容器对象 bean的作用域 Bean对象默认在容器启动时实例化 Lazy在第一次使用时初始化 Bean的管理:第三方Bean 引入依赖,每次解析创建新对象,浪费资源 将第三方对象交给…

如何搭建springBoot项目中的全局异常处理和自定义异常处理

目录 1 什么是异常 2 异常的种类 3 解决异常的方式 4 全局异常处理器和自定义异常处理器 5 测试异常处理 1 什么是异常 异常(Exception)是在程序执行过程中出现的一种特殊情况或错误。它可以是由于程序逻辑错误、运行环境问题、用户输入错误等原因…

【AI基础】反向传播

文章目录 1. 先写出第一步2.将其封装成函数3. pytorch版 1. 先写出第一步 # 定义输入值和期望输出 x_1 40.0 x_2 80.0 expected_output 60.0 初始化# 定义权重 w_1_11 0.5 w_1_12 0.5 w_1_13 0.5 w_1_21 0.5 w_1_22 0.5 w_1_23 0.5w_2_11 1.0 w_2_21 1.0 w_2_31 1…

基于 vLLM 搭建 DeepSeek-V2 Chat 服务

直奔主题。 安装vLLM 官方实现的代码还没有 merge 到 vLLM 主分支,所以直接 git clone DeepSeek 的分支。 git clone https://github.com/zwd003/vllm.git cd vllm pip install -e .源码安装大概耗时 10 分钟。 OpenAI 接口规范启动 官方 Github 放的是单条推理…

通过短信群发平台拓客引流营销的效果好不好?

通过短信群发平台进行营销拓客引流的效果可以是非常显著的,但具体效果会受到多种因素的影响,如目标受众的选择、短信内容的吸引力、发送时间和频率的合理性等。 以下是一些短信群发平台营销拓客引流的优势: 1.广泛覆盖:短…

噪声条件分数网络——NCSN原理解析

1、前言 本篇文章,我们讲NCSN,也就是噪声条件分数网络。这是宋飏老师在2019年提出的模型,思路与传统的生成模型大不相同,令人拍案叫绝!!! 参考论文: ①Generative Modeling by Es…

cesium圆形扩散扫描效果封装

效果 封装类 优化了着色器代码;增加了边框大小调整参数,增加了清除效果方法 注:在页面销毁时需要调用清除方法 CircleDiffusion.clear()/*** circleDiffusion:圆扩散特效封装类**/// 圆扩散 class CircleDiffusion {viewer;last…

docker容器安装nexus3以及nexus3备份迁移仓库数据

一、安装步骤 1.搜索nexus3镜像 docker search nexus3 2.拉取镜像 docker pull sonatype/nexus3或者指定版本 docker pull sonatype/nexus3:3.68.0 3.查看拉取的镜像 docker images | grep "nexus3" 4.启动nexus服务 直接启动 docker run -d --name nexus3 -…

怎么查看公网IP?

在网络通信中,每个设备都会被分配一个IP地址,用于在互联网上进行唯一标识和通信。公网IP是指可以被公开访问的IP地址,可以用来建立远程连接或者进行网络访问等操作。怎么查看公网IP呢?下面将介绍几种常用的方法。 使用命令行查询公…

LabVIEW高温往复摩擦测试系统中PID控制

在LabVIEW开发高温往复摩擦测试系统中实现PID控制,需要注意以下几个方面: 1. 系统建模与参数确定 物理模型建立: 首先,需要了解被控对象的物理特性,包括热惯性、摩擦系数等。这些特性决定了系统的响应速度和稳定性。实验数据获取…

吉时利Keithley 2010数字万用表7.5 位

Keithley 2010数字万用表,7.5 位 吉时利 2010 数字万用表、7.5 位、低噪声万用表将高分辨率与生产应用所需的高速度和高准确度相结合,例如测试精密传感器、换能器、A/D 和 D/A 转换器、调节器、参考、连接器、开关和继电器。2010 基于与吉时利 2000、20…

人工智能应用-实验6-卷积神经网络分类minst手写数据集

文章目录 🧡🧡实验内容🧡🧡🧡🧡代码🧡🧡🧡🧡分析结果🧡🧡🧡🧡实验总结🧡🧡 &#x1f9…

521源码-在线客服-CRMChat网页版客服系统 UNIAPP 全方位在线客服系统源码与管理体系平台

CRMChat客服系统:基于Swoole4Tp6RedisVueMysql构建的高效沟通桥梁 CRMChat是一款独立且高性能的在线客服系统,它结合了Swoole4、Tp6、Redis、Vue以及Mysql等先进技术栈,为用户提供了卓越的在线沟通体验。该系统不仅支持在Pc端、移动端、小程…

列表页9大样式,保准你看了就能掌握。

上文:一张图集齐B端列表页的16大组件,召唤神龙,看后恍然大悟。 普通列表/基础列表/常规列表 不适合移动端展示 复杂列表 加入了统计 适合移动端 项目列表 适合移动端 应用列表 适合移动端 多级列表 复杂的多级结构,下图展示了…

美国教育数据分析

文章目录 第1关:认识数据第2关:数据预处理第3关:数学成绩预测 第1关:认识数据 编程要求 根据提示,在右侧Begin-End区域补充代码,查看数据属性名称。 测试说明 程序会调用你实现的方法,查看数据…

SpringBoot——整合MyBatis

目录 MyBatis 项目总结 1、创建SQL表 2、新建一个SpringBoot项目 3、pom.xml添加依赖 4、application.properties配置文件 5、User实体类 6、UserMapper接口 7、UserMapper.xml映射文件 8、UserController控制器 9、SpringBootMyBatisApplication启动类 10、使用Po…

C语言 | Leetcode C语言题解之第98题验证二叉搜索树

题目: 题解: /*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/ bool isValid(struct TreeNode * root,long left,long right){if(!root){return true;}long…