flink进阶篇

Flink 面试--进阶篇

1、Flink是如何支持批流一体的?
2、Flink是如何做到高效的数据交换的?
3、Flink是如何做容错的?
4、Flink 分布式快照的原理是什么?
5、Flink 是如何保证Exactly-once语义的?
6、Flink 的 kafka 连接器有什么特别的地方?
7、说说 Flink的内存管理是如何做的?
8、说说 Flink的序列化如何做的?
9、Flink中的Window出现了数据倾斜,你有什么解决办法?
10、 Flink中在使用聚合函数 GroupBy、Distinct、KeyBy 等函数时出现数据热点该如何解决?
11、Flink任务延迟高,想解决这个问题,你会如何入手?
12、Flink是如何处理反压的?
13、Operator Chains(算子链)这个概念你了解吗?
14、 Flink什么情况下才会把Operator chain在一起形成算子链?
 
 
 
 
 
 
一、Flink是如何支持批流一体的?
 
 
 
 
本道面试题考察的其实就是一句话:Flink的开发者认为批处理是流处理的一种特殊情况。批处理是有限的流处理。Flink 使用一个引擎支持了DataSet API 和 DataStream API。
 
 
二、Flink是如何做到高效的数据交换的?
 
在一个Flink Job中,数据需要在不同的task中进行交换,整个数据交换是有 TaskManager 负责的,TaskManager 的网络组件首先从缓冲buffer中收集records,然后再发送。Records 并不是一个一个被发送的,而是积累一个批次再发送,batch 技术可以更加高效的利用网络资源。
 
三、Flink是如何做容错的?
 
Flink 实现容错主要靠强大的CheckPoint机制和State机制。Checkpoint 负责定时制作分布式快照、对程序中的状态进行备份;State 用来存储计算过程中的中间状态。
 
四、Flink 分布式快照的原理是什么?
 
Flink的分布式快照是根据Chandy-Lamport算法量身定做的。简单来说就是持续创建分布式数据流及其状态的一致快照。
 
 
 
核心思想是在 input source 端插入 barrier,控制 barrier 的同步来实现 snapshot 的备份和 exactly-once 语义。
 
 
五、Flink 是如何保证Exactly-once语义的?
 
Flink通过实现两阶段提交和状态保存来实现端到端的一致性语义。分为以下几个步骤:
 
开始事务(beginTransaction)创建一个临时文件夹,来写把数据写入到这个文件夹里面
预提交(preCommit)将内存中缓存的数据写入文件并关闭
正式提交(commit)将之前写完的临时文件放入目标目录下。这代表着最终的数据会有一些延迟
丢弃(abort)丢弃临时文件
 
 
若失败发生在预提交成功后,正式提交前。可以根据状态来提交预提交的数据,也可删除预提交的数据。
 
 
 
 
 
七、说说 Flink的内存管理是如何做的?
 
Flink 并不是将大量对象存在堆上,而是将对象都序列化到一个预分配的内存块上。此外,Flink大量的使用了堆外内存。如果需要处理的数据超出了内存限制,则会将部分数据存储到硬盘上。Flink 为了直接操作二进制数据实现了自己的序列化框架。
 
理论上Flink的内存管理分为三部分:
 
Network Buffers:这个是在TaskManager启动的时候分配的,这是一组用于缓存网络数据的内存,每个块是32K,默认分配2048个,可以通过“taskmanager.network.numberOfBuffers”修改
Memory Manage pool:大量的Memory Segment块,用于运行时的算法(Sort/Join/Shuffle等),这部分启动的时候就会分配。下面这段代码,根据配置文件中的各种参数来计算内存的分配方法。(heap or off-heap,这个放到下节谈),内存的分配支持预分配和lazy load,默认懒加载的方式。
User Code,这部分是除了Memory Manager之外的内存用于User code和TaskManager本身的数据结构。
 
 
 
八、说说 Flink的序列化如何做的?
 
Java本身自带的序列化和反序列化的功能,但是辅助信息占用空间比较大,在序列化对象时记录了过多的类信息。
 
Apache Flink摒弃了Java原生的序列化方法,以独特的方式处理数据类型和序列化,包含自己的类型描述符,泛型类型提取和类型序列化框架。
 
TypeInformation 是所有类型描述符的基类。它揭示了该类型的一些基本属性,并且可以生成序列化器。TypeInformation 支持以下几种类型:
 
BasicTypeInfo: 任意Java 基本类型或 String 类型
BasicArrayTypeInfo: 任意Java基本类型数组或 String 数组
WritableTypeInfo: 任意 Hadoop Writable 接口的实现类
TupleTypeInfo: 任意的 Flink Tuple 类型(支持Tuple1 to Tuple25)。Flink tuples 是固定长度固定类型的Java Tuple实现
CaseClassTypeInfo: 任意的 Scala CaseClass(包括 Scala tuples)
PojoTypeInfo: 任意的 POJO (Java or Scala),例如,Java对象的所有成员变量,要么是 public 修饰符定义,要么有 getter/setter 方法
GenericTypeInfo: 任意无法匹配之前几种类型的类
 
针对前六种类型数据集,Flink皆可以自动生成对应的TypeSerializer,能非常高效地对数据集进行序列化和反序列化。
 
 
九、 Flink中的Window出现了数据倾斜,你有什么解决办法?
 
window产生数据倾斜指的是数据在不同的窗口内堆积的数据量相差过多。本质上产生这种情况的原因是数据源头发送的数据量速度不同导致的。出现这种情况一般通过两种方式来解决:
在数据进入窗口前做预聚合
重新设计窗口聚合的key
 
十、 Flink中在使用聚合函数 GroupBy、Distinct、KeyBy 等函数时出现数据热点该如何解决?
 
数据倾斜和数据热点是所有大数据框架绕不过去的问题。处理这类问题主要从3个方面入手:
 
在业务上规避这类问题
例如一个假设订单场景,北京和上海两个城市订单量增长几十倍,其余城市的数据量不变。这时候我们在进行聚合的时候,北京和上海就会出现数据堆积,我们可以单独数据北京和上海的数据。
 
Key的设计上
把热key进行拆分,比如上个例子中的北京和上海,可以把北京和上海按照地区进行拆分聚合。
 
参数设置
Flink 1.9.0 SQL(Blink Planner) 性能优化中一项重要的改进就是升级了微批模型,即 MiniBatch。原理是缓存一定的数据后再触发处理,以减少对State的访问,从而提升吞吐和减少数据的输出量。
 
十一、Flink任务延迟高,想解决这个问题,你会如何入手?
 
在Flink的后台任务管理中,我们可以看到Flink的哪个算子和task出现了反压。最主要的手段是资源调优和算子调优。资源调优即是对作业中的Operator的并发数(parallelism)、CPU(core)、堆内存(heap_memory)等参数进行调优。作业参数调优包括:并行度的设置,State的设置,checkpoint的设置。
 
十二、Flink是如何处理反压的?
1.5版本的TCP的反压,是通过callback实现的,当socket发送数据去receive buffer后,receiver会反馈给send端,目前receiver端的buffer还有多少剩余空间,然后send会根据剩余空间,控制发送速率。
TCP这种方式的弊端:
    1.因为TM中会有多个Task运行,所以单个Task的反压会阻断整个TM的socket,而其他的task也无法向下游发送数据,连checkpoint的barrier也无法发出。
    2.反压传播路径长,导致生效延迟比较大。
 
 
 
1.5版本后采用的credit这种反压机制是在Flink层面上的:
    ResultSubpartition会向InputGate发送这个要发送的量,InputGate返回当前空余量,包含LocalBufferPool的。如果这个时候发现backlog > credit,那么LocalBufferPool就会向NetWorkPool申请内存。
 
长此以往,当credit返回0的时候,表示没有内存缓存了,那么ResultSubpartition接收到credit的时候,就不会继续往netty写数据了。这样socket就不会堵塞了,然后生效延迟也降低了。同时ResultPartition也会不断去探测InputGate是否有空余的空间。
 
 
 
十三、 Operator Chains(算子链)这个概念你了解吗?
 
Flink会在生成JobGraph阶段,将代码中可以优化的算子优化成一个算子链(Operator Chains)以放到一个task(一个线程)中执行:以减少线程之间的切换和缓冲的开销,提高整体的吞吐量和延迟。
 
十四、 Flink什么情况下才会把Operator chain在一起形成算子链?
 
两个operator chain在一起的的条件:
 
上下游的并行度一致
下游节点的入度为1 (也就是说下游节点没有来自其他节点的输入)
上下游节点都在同一个 slot group 中(下面会解释 slot group)
下游节点的 chain 策略为 ALWAYS(可以与上下游链接,map、flatmap、filter等默认是ALWAYS)
上游节点的 chain 策略为 ALWAYS 或 HEAD(只能与下游链接,不能与上游链接,Source默认是HEAD)
两个节点间数据分区方式是 forward(参考理解数据流的分区)
用户没有禁用 chain
 
十五、 说说Flink1.9的新特性?
 
支持hive读写,支持UDF
Flink SQL TopN和GroupBy等优化
Checkpoint跟savepoint针对实际业务场景做了优化
Flink state查询
 
十六、消费kafka数据的时候,如何处理脏数据?
 
可以在处理前加一个fliter算子,将不符合规则的数据过滤出去。
原文地址:https://www.cnblogs.com/huanghanyu/p/12846431.html