大数据面试笔试宝典之Flink面试
1.Flink 是如何支持批流一体的F link 通过一个底层引擎同时支持流处理和批处理.在流处理引擎之上F link 有以下机制1检查点机制和状态机制用于实现容错、有状态的处理;2水印机制用于实现事件时钟;3窗口和触发器用于限制计算范围并定义呈现结果的时间。在同一个流处理引擎之上F link 还存在另一套机制用于实现高效的批处理。1用于调度和恢复的回溯法 由 Microsoft Dryad 引入现在几乎用于所有批处理器;2用于散列和排序的特殊内存数据结构可以在需要时将一部分数据从内存溢出到硬盘上; 3.优化器尽可能地缩短生成结果的时间。2.Flink是如何做容错的F link 实现容错主要靠强大的 CheckPoint 机制和 State 机制。Checkpoint 负责定时制作分布式快照、对程序中的状态进行备份State 用来存储计算过程 中的中间状态。3.Flink分布式快照的原理是什么消息准确一次(exactly once)的语义保证是实时计算的关键特性之一这要求作业从失败恢复 后的状态以及管道中的数据流要和失败时一致通常这是通过定期对作业状态和数据流进行 快照实现的。然而这种方式主要有两点不足1快照进行期间常常要暂停数据流的摄入造成额外延迟和吞吐量下降2快照会过度谨慎地将管道里正在计算的数据也随着状态保存下来导致快照过于庞大。针对以上两个问题F link 引入了异步数据栅栏快照Asynchronous Barrier Snapshot, ABS。ABS 是一种轻量级的快照技术能以低成本备份 DAG有向无环图或 DCG有向有环图计算作业的状态这使得计算作业可以频繁进行快照并且不会对性能产生明显影响。ABS 核 心思想是通过数据栅栏(barrier)来标记触发快照的时间点和对应的数据从而将数据流和快 照时间解耦以实现异步快照操作同时也大大降低了对管道数据的依赖对 DAG 类作业甚 至完全不依赖减小了随之而来的快照大小。3.1barrier 机制F link 使用 checkpoint 做快照借助于 barrier数据栅栏。1 barrier数据栅栏是一种特殊的内部消息用于将数据流从时间上切分为多个窗口 每个窗口对应一系列连续的快照中的一个。2 barrier 由 Job Manager 定时广播给计算任务所有的 Source其后伴随数据流一起流至下 游。3 每个 barrier 是属于当前快照的数据与属于下个快照的数据的分割点。每当接收到 barrier 算子便会将对当前的状态做一次快照成功后将 barrier 以广播形式传 给下游。最后 barrier 会流至作业的 Sink Sink 接受到 barrier 后即向 Job Manager 确认 Job Manager 收到所有 Sink 的确认标志着一个完整快照的生成。快照完成后当前的快照窗口随之关闭算子不会再向上游请求早于这个时间的数据因为 这些数据已经流过整个作业被转化为作业状态的一部分。4.Flink是如何保证Exactly-once语义的Exactly Once 语义Exactly-Once指的是每个输入的事件只影响最终结果一次。即使机器或软件出现故障既 没有重复数据也不会丢数据。4.1.F link 应用程序中的 Exactly-Once 语义F link 利用 checkpoint 对从 source—operator—sink 提供一次完整的容错。Flink checkpoint 快照包含如下内容1对于并行输入数据源快照创建时数据流中的位置偏移2对于 operator存储在快照中的状态指针F link 可以配置一个固定的时间点定期产生 checkpoint将 checkpoint 的数据写入持久存储 系统HDFS。将 checkpoint 数据写入持久存储是异步发生的这意味着 Flink 应用程序在 checkpoint 过程中可以继续处理数据。如果发生机器或软件故障重新启动后F link 应用程序将从最新的 checkpoint 点恢复处理 F link 会恢复应用程序状态将输入流回滚到上次 checkpoint 保存的位置比如 kafka offset 然后重新开始运行。这意味着 Flink 可以像从未发生过故障一样计算结果。总结在 Flink 应用程序内部利用 checkpoint 提供了 Exactly Once。4.2. Flink 应用程序端到端的 Exactly-Once 语义通过 Flink 的 TwoPhaseCommitSink Function 两阶段提交协议能支持端到端KafkaSource KafkaSink的 Exactly-Once 语义。Exactly Once two-phase commit两阶段提交从 Kafka 读取的数据源——转换操作——将数据写回 Kafka 的数据输出端要使数据输出端提供 Exactly-Once 保证它必须将所有数据通过一个事务提交给 Kafka 。提 交捆绑了两个 checkpoint 之间的所有要写入的数据。这可确保在发生故障时能回滚写入的数据。F link 使用两阶段提交协议及预提交阶段来解决这个问题。Pre-commit 预提交阶段在 checkpoint 开始的时候(starting Checkpoint) 即两阶段提交协议的“预提交 ”阶段。当 checkpoint 开始时F link 的 Job Manager 会将 checkpoint barrier将数据流中的记录分为进 入当前 checkpoint 与进入下一个 checkpoint注入数据流。brarrier 在 operator 之间传递。对于每一个 operator它触发 operator 的状态快照写入到 state backend。Pre-commit(Checkpoint starts)数据源保存了消费 Kafka 的偏移量(offset)之后将 checkpoint barrier 传递给下一个 operator。在 operator 过程中比如聚合计算得到了 sum 值此时表明 operator 具有内部状态那么 需要将 sum 值写入 state Backend F link 负责在 checkpoint 成功的情况下正确提交这些写入 的数据到 Job Manager或者在出现故障时中止这些写入的数据 Job Manager。但在 checkpoint 成功之前不需要在预提交阶段执行任何其他操作。Pre-commit without external stateCheckpoint in Progress当输出端DataSink有输出数据写入 Kafka 就具有了外部状态需要做些额外的处理 为了提供 Exactly-Once 保证在预提交阶段除了将其状态写入 state backend 之外数据输 出端还必须预先提交其外部事务这样才能和两阶段提交协议集成。Pre-commit with external state in data sink当 checkpoint barrier 在所有operator 都传递了一遍并且触发的 checkpoint 回调成功完成时 预提交阶段就结束了。所有触发的状态快照都被视为该 checkpoint 的一部分。checkpoint 是整个应用程序状态的快照包括预先提交的外部状态。如果发生故障我们可以回滚到上次 成功完成快照的时间点。commit 提交阶段Job Manager 然后通知所有操作 (包括 DataSource 、Operator 、DataSink) checkpoint 已经成 功了。这是两阶段提交协议的提交阶段Job Manager 为应用程序中的每个 operator 发出 checkpoint 已完成的回调。数据源Data Source和 Operator 没有外部状态因此在提交阶段这些 operator 不必执 行任何操作。但是数据输出端Data Sink拥有外部状态此时应该提交外部事务。总结1一旦所有 operator 完成预提交Pre-commit 才会提交一个 commit。2如果至少有一个预提交Pre-commit 失败则所有其他提交都将中止我们将回滚到 上一个成功完成的 checkpoint。3在预提交Pre-commit 成功之后提交的 commit 需要保证最终成功 operator 和外 部系统都需要保障这点 。如果 commit 失败比如 由于间歇性网络问题 整个 Flink 应用程序将失败应用程序将根据用户的重启策略重新启动Flink 会将 operator 的状态恢 复到已经预提交但尚未真正提交的状态。还会尝试再提交 commit 。这个过程至 关重要因为如果 commit 最终没有成功将会导致数据丢失。5.说说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 : 任意无法匹配之前几种类型的类针对前六种类型数据集F link 皆可以自动生成对应的 TypeSerializer能非常高效地对数据集 进行序列化和反序列化。6.Flink中的Window出现了数据倾斜你有什么解决办法window 产生数据倾斜指的是数据在不同的窗口内堆积的数据量相差过多。本质上产生这种 情况的原因是数据源头发送的数据量速度不同导致的。出现这种情况一般通过两种方式来解 决1在数据进入窗口前做预聚合2重新设计窗口聚合的 key7.Flink中在使用聚合函数GroupBy、Distinct、KeyBy等函数时出现数据热点该如何解决参考答案数据倾斜和数据热点是所有大数据框架绕不过去的问题。处理这类问题主要从 3 个方面入手1在业务上规避这类问题例如一个假设订单场景北京和上海两个城市订单量增长几十倍其余城市的数据量不变。这时候我们在进行聚合的时候北京和上海就会出现数据堆积我们可以单独处理北京和上 海的数据。2Key 的设计上把热 key 进行拆分比如上个例子中的北京和上海可以把北京和上海 按照地区进行拆分聚合。3参数设置F link SQL(Blink Planner) 性能优化中一项重要的改进就是升级了微批模型即 Mini Batch。 原理是缓存一定的数据后再触发处理以减少对 State 的访问从而提升吞吐和减少数据的 输出量。8.Flink任务延迟高想解决这个问题你会如何入手在 Flink 的后台任务管理中我们可以看到 Flink 的哪个算子和 task 出现了反压。最主要的手 段是资源调优和算子调优。资源调优即是对作业中的 Operator 的并发数parallelism、CPUcore、堆内存heap_memory 等参数进行调优。作业参数调优包括并行度的设置State 的设置checkpoint 的设置。9.Flink是如何处理反压的F link 内部是基于 producer-consumer 模型来进行消息传递的F link 的反压设计也是基于这 个 模 型 。 F link 使 用 了 高 效 有 界 的 分 布 式 阻 塞 队 列 就 像 Java 通 用 的 阻 塞 队 列 BlockingQueue一样。下游消费者消费变慢上游就会受到阻塞。F link 什么情况下才会把 Operator chain 在一起形成算子链参考答案两个 operator chain 在一起的的条件1上下游的并行度一致2下游节点的入度为 1 也就是说下游节点没有来自其他节点的输入3上下游节点都在同一个 slot group 中下面会解释 slot group4下游节点的 chain 策略为 ALWAYS可以与上下游链接map 、flatmap 、filter 等默认 是 ALWAYS5上游节点的 chain 策略为 ALWAYS 或 HEAD只能与下游链接不能与上游链接Source 默认是 HEAD6两个节点间数据分区方式是 forward参考理解数据流的分区7用户没有禁用 chain10.说说Flink资源管理中TaskSlot的概念参考答案在 Flink 架构角色中我们提到Task Manager 是实际负责执行计算的 WorkerTask Manager 是 一个 JVM 进程 并会以独立的线程来执行一个 task 或多个 subtask 。为了控制一个 Task Manager 能接受多少个 task F link 提出了 Task S lot 的概念。简单的说Task Manager 会将自己节点上管理的资源分为不同的 Slot固定大小的资源子集。这样就避免了不同 Job 的 Task 互相竞争内存资源但是需要注意的是Slot 只会做内存的隔离。没有做 CPU 的隔 离。11.说说Flink2.0的新特性1.非兼容变更1.1API以下 API 已被完全移除:DataSet API: 请迁移到 DataStream API, 或 Table API/SQL。 详见 如何从 DataSet 迁移到 DataStream。Scala DataStream 和 DataSet API: 请迁移到 Java DataStream API。SourceFuction, SinkFunction 和 Sink V1: 请迁移到 FLIP-27 Source和 Sink V2。TableSoure 和 TableSink: 请迁移到 DynamicTableSource和 DynamicTableSink. 详见 User-defined Sources Sinks。TableSchema, TableColumn 和 Types: 请分别迁移到 Schema, Column和 DataTypes。同时DataStream API 以及 REST API 中部分废弃的方法和字段也已经被移除。注意: 您可能会发现一些已移除的 API 仍然存在于代码库中但被移动到了和原来不同的包路径下。它们现在仅供内部使用并且可能随时发生更改或移除。请 不要再使用 它们.1.2连接器适配计划由于 SourceFunction, SinkFunction 和 SinkV1 API 被移除依赖这些 API 的现有连接器将无法在 Flink 2.x 版本工作需要进行针对性适配。以下是具体的适配计划Flink 2.0 预览版发布后会尽快发布与之适配的 Kafka 连接器新版本。JDBC 和 ElasticSearch 连接器将在 Flink 2.0 的正式版本中适配。我们计划在接下来的 3 个版本即截止到 Flink 2.3中逐步适配剩余的连接器。1.3配置符合以下标准的配置项已被移除:被标注为 Public 并且已弃用至少2个版本。被标注为 PublicEvolving 并且已弃用至少1个版本。在 Flink 2.x 中不再支持旧的配置文件 flink-conf.yaml, 请改用符合标准 YAML 格式的 config.yaml。我们提供了一个迁移工具用于将旧的 flink-conf.yaml 转换为新的 config.yaml。详见 从 flink-conf.yaml 迁移到 config.yaml。在程序中使用硬编码的方式进行配置会带来诸多弊端因此 StreamExecutionEnvironment 和 ExecutionConfig 中与配置相关的 API 不再允许直接传入 Java 对象作为参数。你现在应该通过 Configuration 和 ConfigOption 来进行相应的配置。为了避免暴露过多的内部接口用户自定义函数(UDF) 不再对 ExecutionConfig 具有完整的访问权限。相应地你现在可以直接从 RuntimeContext 中访问这些必要的函数例如 createSerializer(), getGlobalJobParameters() 和 isObjectReuseEnabled()。1.4其它1.x 到 2.x 的升级不保证 状态兼容性。不再支持 Java 8: Java 11 是目前支持的最低 Java 版本。旧的 Hybrid Shuffle 模式 已经被完全移除。2.重要新特性2.1存算分离状态管理过去十年间 Flink 的部署模式、工作负载和硬件的架构都发生了很大的改变。我们已经从计算-存储紧密耦合的 map-reduce 时代进入到了以 Kubernetes 容器化部署为标准的云原生世界。为了 Flink 在云原生时代的未来我们在 Flink 2.0 中引入了基于远程存储的存算分离状态管理。存算分离架构的引入使得 Flink 向云原生领域更进一步。新架构主要解决了以下问题容器化环境下计算节点受本地磁盘大小限制的问题由于RocksDB中LSM结构的周期性 Compaction 导致计算资源尖峰的问题大规模状态快速扩缩容的挑战原生的轻量级和快速检查点受限于 Flink 中现有的阻塞式同步执行模型仅仅将状态存储扩展到从远程 DFS 读写是不够的。在 Flink 2.0 中我们提出了异步执行模型并为此引入了 ForStDB这是一种分离的状态后端解决方案。在当前预览版本下我们使用: NexmarkQ20 完成了一个端到端的示例。 其中包括:异步化执行完整的状态异步访问的API以及检查点支持异步化SQL Join算子基于异步化状态 API实现同步/异步混合式执行基于混合式SQL Plan支持同步算子与异步算子在一个作业内共存性能在直接写入存算分离后的远端存储的场景下提供了不错的性能2.2物化表在 Flink 1.20 中我们以最简可行产品(Minimum Viable Product) 的形式引入了物化表功能。物化表是 Flink SQL 中的一种创新型表类型旨在进一步简化流和批作业的数据处理流程同时提供统一的开发体验。在即将发布的 Flink 2.0 中我们正在增强物化表所支持的功能包括与主流的湖格式进行集成以及生产就绪的调度器实现。2.3批作业的自适应执行此外Flink 正在不断提升其自适应批处理能力。即将发布的 Flink 2.0 将具备基于作业已完成的阶段所提供的信息对逻辑计划和物理计划进行动态优化的能力。初步支持的策略包括动态应用 Broadcast Join 以及对数据倾斜的 Join 进行优化。2.4流式湖仓以 Apache Flink 和 Apache Paimon 的集成为代表的流式湖仓架构将湖仓范式中统一的数据存储、开放格式和成本效益扩展到了实时领域。即将发布的 Flink 2.0 在 Flink 和 Paimon 的集成方面迈出了重要一步Flink 和 Paimon 社区正在密切合作充分结合彼此的优势以及核心功能带来了诸多重要改进包括但不限于使用 Paimon 丰富的合并引擎进行 SQL 执行计划优化、大幅提升 Lookup-Join 的性能、支持 Flink 物化表、以及对自适应批处理和推测执行的支持。12.消费kafka数据的时候如何处理脏数据可以在处理前加一个 fliter 算子将不符合规则的数据过滤出去。13.Flink的反压和Storm有哪些不同Storm 是通过监控 Bolt 中的接收队列负载情况如果超过高水位值就会将反压信息写到 Zookeeper Zookeeper 上的 watch 会通知该拓扑的所有 Worker 都进入反压状态最后 Spout 停止发送 tuple。F link 中的反压使用了高效有界的分布式阻塞队列下游消费变慢会导致发送端阻塞。二者最大的区别是 Flink 是逐级反压而 Storm 是直接从源头降速。14.Flink中水印是什么概念起到什么作用Watermark 是 Flink 为了处理 EventTime 窗口计算提出的一种机制, 本质上是一种时间戳。 一般来讲 Watermark 经常和 Window 一起被用来处理乱序事件。15.Flink中的时间有哪几类F link 中的时间和其他流式计算系统的时间一样分为三类事件时间摄入时间处理时间三种。如果以 EventTime 为基准来定义时间窗口将形成 EventTimeWindow,要求消息本身就应该携 带 EventTime。如果以 IngesingtTime 为基准来定义时间窗口将形成 IngestingTimeWindow, 以 source 的 systemTime 为准。如果以 ProcessingTime 基准来定义时间窗口将形成 ProcessingTimeWindow 以 operator 的 systemTime 为准。16.说说Flink中的状态存储F link 在做计算的过程中经常需要存储中间状态来避免数据丢失和状态恢复。选择的状态 存储策略不同会影响状态持久化如何和 checkpoint 交互。F link 提供了三种状态存储方式MemoryStateBackend、FsStateBackend、RocksDBStateBackend。17.Flink有没有重启策略说说有哪几种F link 实现了多种重启策略。1. 固定延迟重启策略Fixed Delay Restart Strategy2.故障率重启策略Failure Rate Restart Strategy3.没有重启策略No Restart Strategy18.Flink面对数据高峰期时如何处理使用 Kafka 消息队列实现数据消峰然后再使用 Flink 消费数据。19.Flink的checkpoint机制对比spark有什么不同和优势spark streaming 的 checkpoint 仅仅是针对 driver 的故障恢复做了数据和元数据的 checkpoint 。而 flink 的 checkpoint 机制 要复杂了很多它采用的是轻量级的分布式快照实现了每个算子的快照及流动中的数据的快照。20.大数据海量数据去重问题订单业务总量30 多亿数据几十 T 的量阿里子公司解决方案1实时去重数据— — 》ETL 处理— — 》redis可结合 bloomfilter 使用去重设置过期时间淘汰数据 公司保留 7 天 — —》Spark/F link 实时消费。2离线去重直接使用 hive 去重跑 hive shell 脚本即可。21.为什么使用Flink替代Spark主要考虑的是 flink 的低延迟、高吞吐量和对流式数据应用场景更好的支持另外flink 可以很好地处理乱序数据而且可以保证 exactly-once 的状态一致 性。F link 与 Spark 对比1.抽象在 Spark 中对于批处理有 RDD 抽象而 DStream 用于流式传输DStream 内部仍然是 RDD 。因此在 Spark 下面代表的所有数据都使用 RDD 抽象来表示。在 Flink 中为批处理数据集提供了 DataSet 为流应用程序提供了 DataStream。2. 内存管理直到 Spark 1.5 Spark 使用 Java 堆来缓存数据。虽然项目开始时更容易但它导致了内存不 足OOM 问题和垃圾收集gc暂停。因此从 1.5 开始Spark 进入定制内存管理称 为 project tungsten。F link 从第一天起就开始定制内存管理。实际上这是 Spark 向这个方向发展的灵感之一。F link 不仅将数据存储在它的自定义二进制布局中它还可以直接对二进制数据进行操作。在 JVM 上执行自定义内存管理可以提高性能并提高资源利用率。3. 实现语言Spark 在 Scala 中实现。它提供其他语言的 API 如 Java Python 和 R。F link 是用 Java 实现的。它提供其他语言的 API 如 Scala Python 和 R。Spark 和 Flink 都模仿 scala 集合 API 。所以从表面来看两者的 API 看起来非常相似。5. 流Apache Spark 将流式处理视为快速批处理。 Apache Flink 将批处理视为流处理的特殊情况。这两种方法都具有令人着迷的含义。6. SQL 界面截至目前最活跃的 Spark 库之一是 spark-sql 。 Spark 提供了像 Hive 一样的查询语言和像 DSL 这样的 Dataframe 来查询结构化数据。它是成熟的 API 并且在批处理中广泛使用并且很 快将在流媒体世界中使用。目前F link Table API 还不太成熟和完善并且仍处于测试阶段。总结与 Flink 相比Spark 是一个非常成熟和完整的框架但 Flink 确实带来了非常有趣的想法 如自定义内存管理数据集 API 等。 Spark 社区正在认识它并将这些想法融入到 Spark 中。 所以从这个意义上来说F link 正在将大数据处理完全提升到下一个层次。