1、什么是Flink?

Flink项目的理念是:Apache Flink是为分布式、高性能、随时可用以及准确的流处理应用程序打造的开源流处理框架。

Apache Flink是一个框架和分布式处理引擎,用于对无界和有界数据流进行有状态计算。Flink被设计在所有常见的集群环境中运行,以内存执行速度和任意规模来执行计算。

Flink能够提供毫秒级别的延迟,同时保证了数据处理的低延迟、高吞吐和结果的正确性,还提供了丰富的时间类型和窗口计算、Exactly-once(就一次)语义支持,另外还可以进行状态管理,并提供了 CEP(复杂事件处理)的支持。
2、SparkStreaming和Strom的区别?
    Storm    Flink
状态管理    无状态,需用户自行进行状态管理    有状态
窗口支持    对事件窗口支持较弱,缓存整个窗口的所有数据,窗口结束时一起计算    窗口支持较为完善,自带一些窗口聚合方法,并且会自动管理窗口状态
消息投递    At Most Once/At Least Once    At Most Once/At Least Once/Exactly Once
容错方式    ACK机制:对每个消息进行全链路跟踪,失败或超时进行重发    检查点机制:通过分布式一致性快照机制,对数据流和算子状态进行保存;在发生错误时,使系统能够进行回滚
应用现状    在美团点评实时计算业务中已有较为成熟的运用,有管理平台、常用API和相应的文档,大量实时作业基于Storm构建    在美团点评实时计算业务中已有一定应用,但是管理平台、API及文档等仍需进一步完善
3、Flink和SparkStreaming的区别?

这个问题是一个非常宏观的问题,因为两个框架的不同点非常之多,但是在面试时有非常重要的一点一定要回答出来:Flink是标准的实时处理引擎,基于事件驱动;SparkStreaming是微批(Micro-Batch)的模型。
    SparkStreaming    Flink
架构模型    主要角色包括:Master、Worker、Driver和Executor    主要包括:JobManager、TaskManager和Slot
任务调度    连续不间断的生成微小的数据批次,构建有向无环图DAG,会依次创建DStreamGraph、JobGenerator、JobScheduler    根据用户提交的代码生成StreamGraph,经过优化生成JobGraph,然后提交给JobManager进行处理,JobManager会根据JobGraph生成ExecutionGraph,ExecutionGraph是Flink调度最核心的数据结构,JobManager根据ExecutionGraph对Job进行调度
时间机制    只支持处理时间    支持处理时间、事件时间、注入时间;同时也支持watermark机制来处理滞后数据
容错机制    可以设置checkpoint,假如发生故障并重启,可以从上次checkpoint之处恢复,但是这个行为只能使得数据不丢失,可能会重复处理,不能做到恰好一次处理语义    使用两阶段提交(2PC)协议来解决可能重复处理问题,做到恰好一次处理语义
4、Flink的重要特点?

    时间驱动型(Event-driven)

    时间驱动型应用是一类具有状态的应用,它从一个或多个事件流提取数据,并根据到来的时间触发计算、状态更新或其他外部动作

    流与批的世界观
        批处理:有界、持久、大量,非常适合需要访问全套记录才能完成的计算工作,一般用于离线统计
        流处理:无界、实时,无需针对整个数据集执行操作,而是对通过系统传输的每个数据项执行操作,一般用于实时统计

    分层API

    Flink提供的最高层级的抽象是SQL

    越顶层越抽象,表达含义越明显,使用越方便

    越底层越具体,表达能力越丰富,使用越灵活

5、什么是有界流和无界流?

    无界数据流

    无界数据流有一个开始但是没有结束,它们不会在生成时终止并提供数据,必须连续处理无界流,也就是说必须再获取后立即处理event;

    对于无界数据流是无法等待所有数据都到达,因为输入是无界的,并且再任何时间点都不会完成;

    处理无界数据通常要求以特定顺序(例如事件发生的顺序)获取event,以便能够推断结果完整性。

    有界数据流

    有界数据流有明确定义的开始和结束,可以在执行任何计算之前通过获取所有数据来处理有界流;

    处理有界流不需要有序获取,因为可以始终对有界数据集进行排序,有界流的处理也称为批处理。

    这种以流为世界观的架构,获得的最大好处就是具有极低的延迟。

6、Flink的其他特点?

    支持事件事件(event-time)和处理时间(processing time)
    精确一次的状态一致性保证
    低延迟,每秒处理数百万个事件,毫秒级延迟
    与众多常用存储系统连接
    高可用,动态扩展,实现7 * 24小时全天侯运行

7、Flink的组件?

作业管理器(JobManager)

任务管理器(TaskManager)

资源管理器(ResourceManager)

分发器(Dispatcher)
8、JobManager的作用?

    控制一个应用程序执行的主进程,也就是说,每个应用程序都会被一个不同的JobManager所控制执行
    JobManager会先接收到要执行的应用程序
    JobManager会把JobGraph转换成一个物理层面的数据流图,这个图被叫做“执行图”(ExecutionGraph),包含了所有可以并发执行的任务
    JobManager会向资源管理器(ResourceManager)请求执行任务必要的资源,也就是任务管理器(TaskManager)上的插槽(slot);一旦它获取到了足够的资源,就会将执行图分发到真正运行它们的TaskManager上;而在运行过程中,JobManager会负责所有需要中央协调的操作,如检查点(checkpoints)的协调

9、JobManager收到的应用程序包含哪些?

    作业图(JobGraph)
    逻辑数据流图(Logical Dataflow Graph)
    打包了所有的类、库和其他资源的JAR包

10、TaskManager的作用?

    Flink中的工作进程;通常在Flink中会有多个TaskManager运行,每一个TaskManager都包含了一定数量的插槽(slots)
    启动之后,TaskManager会向资源管理器注册它的插槽;收到资源管理器的指令后,TaskManager就会将一个或者多个插槽提供给JobManager调用;JobManager就可以向插槽分配任务(tasks)来执行了
    task的数量由TaskManager内包含的slots的总数量决定,slot的总数量也决定了任务执行的并行度
    在执行过程中,一个TaskManager可以跟其他运行同一应用程序的TaskManager交换数据

11、TaskManager执行任务的数量由什么来决定的?

插槽的数量限制了TaskManager能够执行的任务数量
12、ResourceManager的作用?

    主要负责管理任务管理器(TaskManager)的插槽(slot)
    Flink为不同的环境和资源管理工具提供了不同资源管理器,比如YARN、Mesos、K8s以及Standalone部署
    当JobManager申请插槽资源时,ResourceManager会将有空闲插槽的TaskManager分配给JobManager;如果ResourceManager没有足够的插槽来满足JobManager的请求,它还可以向资源提供平台发起会话,以提供启动TaskManager进程的容器
    另外,ResourceManager还负责终止空闲的TaskManager,释放计算资源

13、Flink的资源单元?

TaskManager插槽是Flink中定义的处理资源单元
14、分发器的作用?

    可以跨作业运行,它为应用提交提供了REST接口
    当一个应用被提交执行时,分发器就会启动并将应用移交给一个JobManager
    Dispatcher也会启动一个Web UI,用来方便地展示和监控作业执行地信息
    Dispatcher在架构中可能并不是必需地,这取决于应用提交运行的方式

15、任务提交流程

Flink的各个组件的交互协作

在这里插入图片描述

如果部署的集群环境不同(如YARN、Mesos、K8s以及Standalone等),其中一些步骤可以被省略,或是有些组件会运行在同一个JVM进程中

Flink集群部署到YARN上

在这里插入图片描述
16、Flink的程序由几部分组成?

所有的Flink程序都是由三部分组成的:Source、Transformation和Sink

Source:负责读取数据源

Transformation:利用各种算子进行处理加工

Sink:负责输出
17、Flink的执行图分为几层?

Flink中的执行图可以分成四层:

StreamGraph:根据用户通过Stream API编写的代码生成的最初的图;用来表示程序的拓扑结构

JobGraph:StreamGraph经过优化后生成了JobGraph,提交给JobManager的数据结构;主要的优化为,将多个符合条件的节点链接在一起,这样可以减少数据在节点之间流动所需要的序列化/反序列化/传输消耗

ExecutionGraph:JobManager根据JobGraph生成ExecutionGraph;ExecutionGraph是JobGraph的并行化版本,是调度层最核心的数据结构

物理执行图:JobManager根据ExecutionGraph对Job进行调度后,在各个TaskManager上部署Task后形成的“图”,并不是一个具体的数据结构
18、算子之间数据传输的形式?

    One-to-one:类似于Spark中的窄依赖

    stream(比如在source和map operator之间)维护着分区以及元素的顺序,那意味着map算子的子任务看到的元素的个数以及顺序跟source算子的子任务生产的元素的个数、顺序相同,map、fliter、flatMap等算子都是one-to-one的对应关系

    Redistributing:类似于Spark中的宽依赖

    stream(map()跟keyBy/window之间或者keyBy/window跟sink之间)的分区会发生改变;每一个算子的子任务依据所选择的transformation发送数据到不同的目标任务。例如,keyBy()基于hashCode重分区、broadcast和rebalance会随机重新分区,这些算子都会引起redistribute过程,而redistribute过程就类似于Spark中的shuffle过程

19、Flink的任务链?任务链的要求?

Flink采用了一种称为任务链的优化技术,可以在特定条件下减少本地通信的开销;为了满足任务链的要求,必须将两个或多个算子设为相同的并行度,并通过本地转发(local forward)的方式进行连接

相同并行度的one-to-one操作,Flink这样相连的算子连接在一起形成一个task,原来的算子成为u里面的subtask

并行度相同、并且是one-to-one操作,两个条件缺一不可
20、Flink中Split和Select?

在这里插入图片描述

DataStream → SplitStream:根据某些特征把一个DataStream拆分成两个或者多个DataStream

在这里插入图片描述

SplitStream →DataStream:从一个SplitStream中获取一个或者多个DataStream
21、Flink中Union与Connect区别?

    Union之前两个流的类型必须是一样;Connect可以不一样,在之后的CoMap中再去调整成为一样的
    Union可以操作多个流;Connect只能操作两个流

22、Flink中的rich函数?

“富函数”是DataStream API提供的一个函数类的接口,所有Flink函数类都有其Rich版本

它与常规函数的不同在于,可以获取运行环境的上下文,并拥有一些生命周期方法,所以可以实现更复杂的功能

    RichMapFunction
    RichFlatMapFunction
    RichFilterFunction
    …

Rich Functions有一个生命周期的概念,典型的生命周期方法有:

    open():初始化方法,当一个算子(例如map或者filter)被调用之前open()会被调用
    close():生命周期中的最后一个调用的方法,做一些清理工作
    getRuntimeContext():提供了函数的RuntimeContext的一些信息,例如函数执行的并行度,任务的名字,以及state状态

23、Flink的window分为几种?

    CountWindow:按照指定的数据条数生成一个Window,与时间无关
    TimeWindow:按照时间生成Window
    Global Window:全局窗口

24、TimeWindow分为哪几种?

    滚动窗口(Tumbling Windows):将数据依据固定的窗口长度对数据进行切片

    特点:时间对齐,窗口长度固定,没有重叠

    适用场景:适合做 BI 统计等(做每个时间段的聚合计算)

    滑动窗口(Sliding Windows):是固定窗口的更广义的一种形式,滑动窗口由固定的窗口长度和滑动间隔组成

    特点:时间对齐,窗口长度固定,可以有重叠

    适用场景:对最近一个时间段内的统计

    会话窗口(Session Windows):由一系列事件组合一个指定时间长度的timeout间隙组成,类似于web应用session,也就是一段时间没有接收到新数据就会生成新的窗口

    特点:时间无对齐

25、WindowFunction对数据的计算分为两类?

    增量聚合函数(incremental aggregation functions)

    每条数据到来就进行计算,保持一个简单的状态

    典型的增量聚合函数有ReduceFunction,AggregateFunction

    全窗口函数(full window functions)

    先把窗口所有数据收集起来,等到计算的时候会遍历所有数据

    ProcessWindowFunction就是一个全窗口函数

26、Flink提供了8个ProcessFunction?

    ProcessFunction
    KeyedProcessFunction
    CoProcessFunction
    ProcessJoinFunction
    BroadcastProcessFunction
    KeyedBroadcastProcessFunction
    ProcessWindowFunction
    ProcessAllWindowFunction

27、Flink的TimerService?

Context和OnTimerContext所持有的TimerService对象拥有以下方法:

    currentProcessingTime():Long返回当前处理时间
    currentWatermark():Long返回当前watermark的时间戳
    registerProcessingTimeTimer(timestamp: Long): Unit:会注册当前key的processing time的定时器;当processing time到达定时时间时,触发timer
    registerEventTimeTimer(timestamp: Long): Unit:会注册当前key的event time定时器;当水位线大于等于定时器注册的时间时,触发定时器执行回调函数
    deleteProcessingTimeTimer(timestamp: Long): Unit:删除之前注册处理时间定时器;如果没有这个时间戳的定时器,则不执行
    deleteEventTimeTimer(timestamp: Long): Unit:删除之前注册的事件时间定时器,如果没有此时间戳的定时器,则不执行

当定时器timer触发时,会执行回调函数onTimer();注意定时器timer只能在keyed streams上面使用
28、Flink中状态的类型?

    算子状态(Operator State)
    键控状态(Keyed State)

29、Flink为算子状态提供三种基本数据结构?

    列表状态(List state)

    将状态表示为一组数据的列表

    联合列表状态(Union list state)

    也将状态表示为数据的列表;它与常规列表状态的区别在于,在发生故障时,或者从保存点(savepoint)启动应用程序时如何恢复

    广播状态(Broadcast state)

    如果一个算子有多项任务,而它的每项任务状态又都相同,那么这种特殊情况最适合应用广播状态

30、Flink状态一致性的级别?

    at-most-once

    这其实是没有正确性保障的委婉说法,故障发生之后,计数结果可能丢失

    at-least-once

    这表示计数结果可能大于正确值,但绝对不会小于正确值;也就是说,计数程序在发生故障后可能多算,但是绝不会少算

    exactly-once
    这指的是系统保证在发生故障后得到的计数结果与正确值一致

31、什么是端到端的一致性?

目前我们看到的一致性保证都是由流处理器实现的,也就是说都是在 Flink 流处理器内部保证的;而在真实应用中,流处理应用除了流处理器以外还包含了数据源(例如Kafka)和输出到持久化系统

端到端的一致性保证,意味着结果的正确性贯穿了整个流处理应用的始终;每一个组件都保证了它自己的一致性,整个端到端的一致性级别取决于所有组件中一致性最弱的组件
32、端到端的一致性具体可以划分?

    内部保证:依赖checkpoint

    source端:需要外部源可重设数据的读取位置

    sink端:需要保证从故障恢复时,数据不会重复写入外部系统

33、sink端保证一致性的两种方式?

    幂等写入

    所谓幂等操作,是说一个操作,可以重复执行很多次,但只导致一次结果更改,也就是说,后面再重复执行就不起作用了

    事务写入

    需要构建事务来写入外部系统,构建的事务对应着checkpoint,等到checkpoint真正完成的时候,才把所有对应的结果写入sink系统中

34、事务性写入具体又有两种实现方式?

    预写日志(WAL)

    两阶段提交(2PC)

35、Flink + Kafka如何实现端到端的exactly-once语义?

    内部:利用checkpoint机制,把状态存盘,发生故障的时候可以恢复,保证内部的状态一致性
    source:kafka consumer作为source,可以将偏移量保存下来,如果后续任务出现了故障,恢复的时候可以由连接器重置偏移量,重新消费数据,保证一致性
    sink:kafka producer作为sink,采用两阶段提交sink,需要实现一个TwoPhaseCommitSinkFunction

36、Flink的StateBackend?

每传入一条数据,有状态的算子任务都会读取和更新状态

由于有效的状态访问对于处理数据的低延迟至关重要,因此每个并行任务都会在本地维护其状态,以确保快速的状态访问

状态的存储、访问以及维护,由一个可插入的组件决定,这个组件就叫做状态后端(state backend)
37、几种状态后端的区别?

    MemoryStateBackend
        内存级的状态后端,会将键控状态作为内存中的对象进行管理,将它们存储在TaskManager的JVM堆上,而将checkpoint存储在JobManager的内存中
        特点:快速、低延迟,但不稳定

    FsStateBackend
        将checkpoint存到远程的持久化文件系统(FileSystem)上,而对于本地状态,跟MemoryStateBackend一 样,也会存在TaskManager的JVM堆上
        同时拥有内存级的本地访问速度,和更好的容错保证

    RocksDBStateBackend
        将所有状态序列化后,存入本地的RocksDB中存储
        注意:RocksDB的支持并不直接包含在flink中,需要引入依赖