那些年你错过的数开/数分面经
面经5.0重磅来啦!!!技术栈涵盖了Hadoop、Hive、Zookeeper、Kafka、Spark、Flink、Mysql、Mysql原和架构、Java、数仓、真实面试题
148、Flink架构
Flink是一个框架和分布式处理引擎,用于对无界和有界数据流进行有状态计算
特点:
高吞吐和低延迟:每秒数百万个事件,毫秒级延迟
结果的准确性:提供了事件时间和处理时间语义,提供结果的一致性
精确一次的状态的一致性保证
jobmanager包含三个组件:
jobmaster:是jobmanager中最核心的组件,负责处理单独的job,jobmaster和具体的job是一一对应的
resourceManager
:负责资源的分配和管理,所谓的资源,只要是指taskmanager的任务槽,任务槽就是Flink集群中的资源调配单元,包含了机器用来执行计算的一组cpu和内存资源
分发器(Dispatcher):负责提供一个rest接口,用来提交应用,并且负责为每一个新提交的作业启动一个新的jobmanager组件
TaskManager:数据流的具体计算就是它来做的,它可以启动多个独立的线程,来并行执行多个子任务(subtask)。每个taskmanager都包含一个定数据量的任务槽,slot是资源调度的最小单位
Flink主要包含TaskManager、JobManager、Client三种角色
1、JobManager扮演着集群中的管理者Master的角色,它是整个集群的协调者,负责接收Flink Job,协调检查点,Failover 故障恢复等,同时管理Flink集群中从节点TaskManager。
2、TaskManager是实际负责执行计算的Worker,在其上执行Flink Job的一组Task,每个TaskManager负责管理其所在节点上的资源信息,如内存、磁盘、网络,在启动的时候将资源的状态向JobManager汇报。
补充:并行度的概念
一个特定算子的子任务的个数被称为并行度,一个流的并行度,指的是其所有算子中最大的并行度
补充:算子链
一个数据流在算子之间传输数据的形式可以是一对一的直通,也可以是打乱的重分区模式
一对一:算子之间不需要重分区,也不需要调整数据的顺序,保证着一对一的关系,类似Spark中的窄依赖
重分区:数据流的分区会发生改变,根据数据传输的策略,把数据发送到下游不同的目标任务中,类似Spark中的shuffle
合并算子链:并行度一一对应的算子操作,可以连接一起,形成一个大的任务,称为算子链
优点:可以减少线程之间的切换和基于缓存区的数据交换,在减少延时的同时提升吞吐量
客户端在提交任务的时候会优化操作,能进行合并的operator会被合并为一个operator,合并后的operator称为算子链,每个算子链会在taskmanager上独立的线程中执行
补充:任务槽的概念
每个任务槽(task slot)其实表示了TaskManager拥有计算资源的一个固定大小的子集。这些资源就是用来独立执行一个子任务的。Flink将进程的内存进行了划分到多个slot中
任务槽是静态的概念,是指taskmanager的并发执行能力。并行度是动态的概念,是taskmanager运行时候实际使用的并发能力;
槽共享:即使是不同任务的子任务,只要来自同一个作业,一个槽可以保存作业的整个管道,允许插槽共享
优点是:只需要计算job中最高并行度的task slot;资源分配更加公平,可以提高并行度
补充:创建执行环境的方式
getExecutionEnvironment:根据上下文进行创建执行环境,如果是独立运行的,就返回一个本地执行环境,如果是创建了jar包,就返回集群的执行环境
createLocalEnvironment:返回一个本地执行环境,默认并行度就是本地CPU的核心数
createRemoteEnvironment:返回一个集群执行环境,需要指定ip和端口号
补充:Flink中支持的数据类型
java所有的类型包括包装类,再加上void、string、date、BigDecimal和BigInteger。包括基本类型数组(PRIMITIVE_ARRAY)和对象数组(OBJECT_ARRAY)。
包括java的元组类型tuple,从tuple0——tuple25
包括scala的元组不支持空字段
POJO类等。。。。。。
149、Flink的窗口了解哪些,都有什么区别,有哪几种?如何定义?
1、按照驱动类型区分:
2、按照窗口分配数据的规则分类
滚动窗口:由固定的大小,是一种对数据进行均匀切片的划分方式,窗口之间没有重叠,也不会由间隔,首尾相接
滑动窗口
:窗口之间并不是首尾相连,而是错开的位置,
当滑动步长==窗口大小时候,就和滚动窗口一样
当滑动步长<窗口大小时候,窗口就会重叠,出现数据分配到多个窗口的现象出现
会话窗口:类似session会话,数据来了就保持会话窗口开启,如果接下来还有数据到来,就一直保持会话,如果一段时间没收到数据,就认为会话超时,窗口自动关闭
全局窗口:无界流的数据永无止境,没有结束实际
150、Flink中的时间语义
Event time:事件创建的事件,一般是在外部系统事件产生的事件
优势:基于事件时间的处理可以保证结果的准确性;处理具有窗口操作的场景,事件时间可以确保窗口的精确性和一致性;适用于对数据进行实时分析和处理的场景
Ingestion Time:数据进入Flink的事件
能够保证摄入数据的顺序性,不会受数据到达顺序的影响
Process time:执行操作算子的本地系统事件,与机器相关
优势:计算成本较低,不需要额外的时间戳和水位线来管理;适用于实时性要求不高的场景
151、Flink中的水位线
特性:
水位线是插入到数据流中的一个标记
水位线的主要内容是一个时间戳,用来表示当前时间的进展
水位线是基于数据的时间戳生成的
水位线的时间戳必须单调递增
水位线可以通过设置延迟时间,来保证正确的乱序数据
水位线的传递
上游多个水位线往下游发送时候,取各个水位线的最小值作为当前水位线
watermarks是基于已经收集的消息来估算是否还有消息未到达,watermark相当于一个endline,一旦watermark大于某个window的end_time,就意味windows_end_time和watermark时间相同的窗口就开始执行计算
152、Flink中窗口和水位线的关系
Flink想要更加高效方便地处理无界流,一种方式就是将无界流数据切割成有限的“数据块”,这就是窗口的概念
窗口和水位线的提出,使其在一定范围以内可以正确处理数据乱序的现象
一般当水位线时间大于窗口的结束时间,开始触发窗口的计算
window的作用是为了周期性的获取数据
watermark的作用是防止数据出现乱序,事件事件内获取不到指定的全部数据,而做的一种方法
allowlateness是将窗口关闭时间再延长一点
sideoutput是最后的兜底操作,所有过期延期数据,指定窗口已经彻底关闭,就会把数据放到侧输出流
153、Flink的Checkpoint机制
checkpoint就是Flink会在指定时间段上保存状态的机制,如果Flink挂了,就可以将上一次的状态信息捞起来,重放还没保存的数据来执行,就中实现exactly once。状态只持久化一次到最终的存储上。
应该在所有任务都恰好处理完一个相同的输入数据的时候,将他们的状态保存下来,在重新恢复时候,只需要让source任务向数据源重新提交偏移量、请求重放数据就可以
检查点分界线:专门用来触发检查点保存的时间点,source可以在当前数据流中插入这个结构,之后的任务只要遇到它就开始对状态做持久化快照保存。
补充:Checkpoint 存储位置在哪里
默认情况下,检查点存储在JobManager的堆内存中,也可以存储在本地文件目录或者HDFS上(存储到分布式文件系统、分布式数据库、对象存储服务)
checkpoint的存储格式包括:元数据信息、状态数据、元数据索引
env.enableCheckpointing(6000); env.getCheckpointConfig().setCheckpointStorage("文件目录"); env.getCheckpointConfig().setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE);
补充:检查点算法
在Flink中,采用了基于Chandy-Lamport算法的分布式快照算法
检查点分界线Barrier:所有任务只要遇到它就开始对状态做持久化快照保存,也代表之前的数据都处理完了,把一条流上的数据按照不同的检查点分隔开,所以就叫做检查点的“分界线”(Checkpoint Barrier)。
1、分布式快照算法 Barrier对齐精准一次
水位线表示之前的数据全部到齐了,barrier表示之前所有数据的状态更改保存入当前检查点
两个原则:
1、当上游任务向多个并行下游任务发送barrier时,需要广播出去;
2、而当多个上游任务向同一个下游任务传递分界线时,需要在下游任务执行“分界线对齐”操作,也就是需要等到所有并行分区的barrier都到齐,才可以开始状态的保存。
2、 分布式快照算法(Barrier对齐的至少一次)
补充:Flink中的SavePoint机制
savepoint:用户手动执行,不会过期,相当于备份
checkpoint:应用定时触发,用户保存状态,会过期
154、并行度和算子链
一个流程序的并行度,可以认为是所有算子中最大的并行度
一个数据流在算子之间传输数据的形式可以说是一对一、可以说是打乱的重分区的,一对一类似于spakr中的窄依赖;重分区类似宽依赖
合并算子链:并行度相同的一对一算子操作,可以直接链接在一起形成一个大的任务,每个task被称为一算子链
将算子链合并成task是非常有效的优化:可以减少线程之间的切换和基于缓存区的数据交换,在减少延时的同时提升吞吐量
补充:设置Flink算子并行度以及优先级
1、在代码中设置
stream.map(word -> Tuple2.of(word, 1L)).setParallelism(2);
2、提交应用时候设置等价于在webUI上设置并行度
bin/Flink run –p 2 –c com.atguigu.wc.SocketStreamWordCount ./FlinkTutorial-1.0-SNAPSHOT.jar
3、配置文件指定
并行度优先级:算子代码>env代码>提交时候指定>配置文件
155、转换算子
1、map
一一映射,消费一个元素就产出一个元素,返回类型还是datastream
2、filter
设置一个布尔过滤,对于流内的元素进行判断,若为true则元素正常输出,若为false则元素被过滤掉
3、flatMap
主要是将数据流中的整体拆分成一个又一个的个体使用,消费一个元素,产生多个元素,返回值类型取决于所传参数的具体逻辑,可以与原数据流相同,也可以不同
4、Aggregation
按键分区keyby
keyby是聚合前必须要用到的一个算子,通过指定键,可以将一条流从逻辑上划分成不同的分区,
在内部是通过计算key的哈希值,对分区进行取模运算得到的,keyby得到的记过不再是datastream,而是keyedstream,分区流或者键控流
5、reduce
对已有的数据进行规约处理,把每一个新输入的数据和当前已经规约出来的值,再做一个聚合计算
156、富函数
Flink的所有函数都有rich版本,不同于常规函数的是:富函数类可以获取运行时候的上下文,并拥有一些生命周期方法
open()方法:是富函数初始化方法,开启一个算子生命周期,一个算子的实际工作方法map或者filter被调用之前,open方法会首先被调用
close():生命周期中的最后一个调用的方法,
157、物理分区算子
1、随机分区:这是最简单的分区方式,调用datastream.shuffle()将数据随机地分配到下游算子中的并行任务中去
2、轮询分区:按照先后顺序将数据做依次分发,将输入流数据平均地分配到下游的并行任务中去 stream.rebalance()
3、重缩放分区:只会将数据轮询发送到下游并行任务中的一部分去,stream.rescale()
4、广播:数据会在不同的分区逗保留一份,将输入数据复制并分发到下游算子的所有并行任务中去,调用DataStream的broadcast()方法
5、全局分区:调用.global()方法,会将所有的输入流数据都发送到下游算子的第一个并行子任务中去