Flink面试题及详细答案100道(1-20)- 基础概念与架构
《前后端面试题
》专栏集合了前后端各个知识模块的面试题,包括html,javascript,css,vue,react,java,Openlayers,leaflet,cesium,mapboxGL,threejs,nodejs,mangoDB,SQL,Linux… 。
文章目录
- 一、本文面试题目录
- 1. 什么是Flink?它与Spark、Storm等流处理框架相比有哪些核心优势?
- 2. 简述Flink的核心架构组件及其作用
- 3. Flink中的“流(Stream)”和“批(Batch)”是如何统一的?其设计思想是什么?
- 4. 解释Flink中的“状态(State)”概念,为什么状态管理对Flink至关重要?
- 5. 什么是Flink的“时间特性”?包括哪几种时间类型,各自的应用场景是什么?
- 6. 简述Flink的“检查点(Checkpoint)”机制,其作用是什么?
- 7. Flink的“保存点(Savepoint)”与检查点有何区别?何时需要使用保存点?
- 8. 解释Flink中的“并行度(Parallelism)”概念,如何设置和调整并行度?
- 9. Flink的“Slot”是什么?它与并行度的关系是什么?
- 10. 什么是Flink的“作业图(JobGraph)”“执行图(ExecutionGraph)”和“物理执行图(Physical Graph)”?三者的转换关系是什么?
- 11. Flink支持哪几种部署模式?各有什么特点?
- 12. 解释Flink中的“算子(Operator)”概念,常见的算子有哪些?
- 13. Flink的“数据交换策略(Data Exchange Strategy)”有哪几种?分别适用于什么场景?
- 14. 什么是Flink的“窗口(Window)”?为什么窗口是流处理中的核心概念?
- 15. Flink的“背压(Backpressure)”是什么?如何检测和处理背压问题?
- 16. 简述Flink的“类型系统(Type System)”,为什么需要关注数据类型?
- 17. Flink的“ExecutionConfig”有什么作用?可以配置哪些核心参数?
- 18. 什么是Flink的“动态缩放(Dynamic Scaling)”?其实现原理是什么?
- 19. 解释Flink中的“Watermark”机制,它如何解决数据乱序问题?
- 20. Flink的“Exactly-Once”语义是如何保证的?依赖哪些核心机制?
- 二、100道Flink 面试题目录列表
一、本文面试题目录
1. 什么是Flink?它与Spark、Storm等流处理框架相比有哪些核心优势?
Flink是一个开源的分布式流处理框架,专注于实时数据处理和批处理,能够同时支持高吞吐、低延迟、 Exactly-Once语义和状态管理等特性。
核心优势:
- 处理模型:Flink以“流优先”为设计理念,将批处理视为流处理的一种特殊情况(有界流),而Spark基于微批处理模拟流处理,Storm虽为纯流处理但缺乏批处理能力。
- 时间特性:Flink内置事件时间(Event Time)支持,能更准确处理乱序数据;Spark Streaming依赖处理时间(Processing Time),对乱序数据处理能力较弱。
- 状态管理:Flink提供丰富的状态后端(如RocksDB)和状态访问API,支持大规模状态存储和高效访问;Storm的状态管理需依赖外部系统。
- 容错机制:Flink的Checkpoint机制轻量且高效,能在毫秒级完成快照;Spark Streaming的Checkpoint开销较大。
- 延迟与吞吐:Flink可实现毫秒级延迟且保持高吞吐;Spark Streaming延迟通常在秒级,Storm虽延迟低但吞吐受限。
2. 简述Flink的核心架构组件及其作用
Flink的核心架构组件包括:
- JobManager:集群的“大脑”,负责作业的调度和管理。
- 接收客户端提交的作业,生成执行计划(ExecutionGraph)。
- 协调Checkpoint,故障恢复时重新分配任务。
- 管理TaskManager的资源分配。
- TaskManager:执行具体任务的工作节点。
- 运行任务(Task),处理数据并与其他节点交换数据。
- 提供Slot资源(任务运行的内存隔离单元)。
- 向JobManager汇报自身状态和资源使用情况。
- ResourceManager:负责集群资源的管理和分配(仅在YARN/K8s等集群模式下生效)。
- 为新提交的作业分配TaskManager资源。
- 监控资源使用情况,回收闲置资源。
- Dispatcher:接收客户端连接和作业提交,为每个作业启动对应的JobManager。
- 提供Web UI用于作业监控和管理。
- 在高可用模式下协调JobManager的故障转移。
3. Flink中的“流(Stream)”和“批(Batch)”是如何统一的?其设计思想是什么?
Flink通过“有界流”和“无界流”的概念统一流处理和批处理:
- 无界流(Unbounded Stream):数据持续产生,无终止点(如实时日志),对应传统流处理场景。
- 有界流(Bounded Stream):数据有明确的开始和结束(如历史数据文件),对应批处理场景。
设计思想:
- 以流处理为基础,将批处理视为流处理的特例(有界流),共享同一套核心引擎。
- 统一的API层(DataStream API)同时支持两种模式,开发者无需切换框架即可处理不同类型的数据。
- 优化器根据数据是否有界自动调整执行策略(如批处理可使用更高效的排序和 shuffle 算法)。
示例:同一套代码可处理实时流和历史批数据
// 读取无界流(Kafka)
DataStream<String> stream = env.addSource(new FlinkKafkaConsumer<>("topic", new SimpleStringSchema(), props));// 读取有界流(文件)
DataStream<String> batch = env.readTextFile("file:///path/to/data");// 统一处理逻辑
stream.filter(...).map(...).print();
batch.filter(...).map(...).print();
4. 解释Flink中的“状态(State)”概念,为什么状态管理对Flink至关重要?
状态(State)是Flink算子在处理数据过程中需要保存的中间结果或元数据(如计数器、聚合结果、窗口状态等)。
状态管理的重要性:
- 支持有状态计算:许多流处理场景(如累加计数、会话窗口、关联分析)需要依赖历史状态。
- 保证容错性:通过Checkpoint机制持久化状态,故障恢复时可恢复到最近的一致状态。
- 提升性能:Flink提供本地状态存储(如内存或RocksDB),避免频繁访问外部系统。
状态类型:
- 托管状态(Managed State):由Flink自动管理,支持Checkpoint和故障恢复(如ValueState、ListState)。
- 原始状态(Raw State):用户自行管理,Flink仅保存字节数组,不提供序列化和恢复支持。
示例:使用ValueState统计单词出现次数
public class WordCountState extends RichFlatMapFunction<String, Tuple2<String, Integer>> {private transient ValueState<Integer> countState;@Overridepublic void open(Configuration parameters) {// 初始化状态ValueStateDescriptor<Integer> descriptor = new ValueStateDescriptor<>("count", Integer.class);countState = getRuntimeContext().getState(descriptor);}@Overridepublic void flatMap(String word, Collector<Tuple2<String, Integer>> out) throws Exception {Integer count = countState.value() == null ? 0 : countState.value();count++;countState.update(count);out.collect(new Tuple2<>(word, count));}
}
5. 什么是Flink的“时间特性”?包括哪几种时间类型,各自的应用场景是什么?
Flink的时间特性指流处理中对时间的定义方式,用于处理事件的时序关系,尤其是乱序数据。
三种时间类型:
- 事件时间(Event Time):事件实际产生的时间(如日志中的timestamp字段)。
- 应用场景:需要精确计算事件时序的场景(如实时监控、异常检测),不受处理延迟影响。
- 处理时间(Processing Time):事件被Flink算子处理时的系统时间。
- 应用场景:对时间精度要求不高,追求低延迟的场景(如实时报表预览)。
- 摄入时间(Ingestion Time):事件进入Flink系统的时间(如Source算子接收数据的时间)。
- 应用场景:介于事件时间和处理时间之间,无需显式指定事件时间字段时使用。
示例:设置事件时间和Watermark
// 设置事件时间特性
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);// 从数据中提取事件时间并生成Watermark
DataStream<Event> stream = env.addSource(...).assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor<Event>(Time.seconds(5)) {@Overridepublic long extractTimestamp(Event element) {return element.getTimestamp(); // 提取事件时间字段}});
6. 简述Flink的“检查点(Checkpoint)”机制,其作用是什么?
Checkpoint是Flink实现容错的核心机制,通过周期性地对算子状态和数据流位置进行快照,实现故障后的状态恢复。
工作原理:
- JobManager的Checkpoint Coordinator发起Checkpoint。
- 各算子接收到Checkpoint请求后,将自身状态写入持久化存储(如HDFS)。
- 状态写入完成后,算子向Coordinator确认Checkpoint完成。
- 所有算子完成后,Checkpoint标记为成功。
作用:
- 故障恢复:当TaskManager崩溃时,JobManager可基于最近的Checkpoint重启作业并恢复状态。
- 保证Exactly-Once语义:通过Checkpoint和两阶段提交(2PC)确保数据处理的一致性。
示例:配置Checkpoint
// 启用Checkpoint,间隔1000ms
env.enableCheckpointing(1000);// 配置Checkpoint参数
CheckpointConfig config = env.getCheckpointConfig();
config.setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE); // 精确一次语义
config.setMinPauseBetweenCheckpoints(500); // 两次Checkpoint最小间隔
config.setCheckpointTimeout(60000); // 超时时间
config.setMaxConcurrentCheckpoints(1); // 最大并发Checkpoint数
7. Flink的“保存点(Savepoint)”与检查点有何区别?何时需要使用保存点?
区别:
- 触发方式:Checkpoint由系统自动周期性触发;Savepoint需用户手动触发。
- 用途:Checkpoint用于故障恢复,生命周期与作业绑定(作业终止后自动删除);Savepoint用于作业版本升级、迁移或暂停后重启,需手动删除。
- 存储格式:Savepoint使用更稳定的二进制格式,跨版本兼容性更好;Checkpoint格式可能随版本变化。
使用场景:
- 作业升级:修改代码后,从Savepoint恢复作业以保留历史状态。
- 集群迁移:将作业从一个集群迁移到另一个集群。
- 资源调整:调整并行度或资源配置后重启作业。
- 暂停与重启:暂时停止作业,后续从相同状态继续运行。
示例:触发和使用Savepoint
# 触发Savepoint
bin/flink savepoint <job-id> <savepoint-path># 从Savepoint恢复作业
bin/flink run -s <savepoint-path> -c <main-class> <jar-file>
8. 解释Flink中的“并行度(Parallelism)”概念,如何设置和调整并行度?
并行度(Parallelism)指Flink作业中算子的任务(Task)数量,决定了作业的并行处理能力。每个Task独立运行在不同的Slot中。
设置方式(优先级从高到低):
- 算子级别:
operator.setParallelism(n)
- 执行环境级别:
env.setParallelism(n)
- 客户端提交时:
bin/flink run -p n <jar-file>
- 配置文件级别:
flink-conf.yaml
中设置parallelism.default
示例:设置并行度
// 环境级别并行度
ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
env.setParallelism(4);// 算子级别并行度(覆盖环境设置)
DataStream<String> stream = env.readTextFile("data.txt").filter(...).map(...).setParallelism(8); // 该map算子并行度为8
调整并行度:通过Savepoint停止作业后,重新提交时指定新的并行度。
9. Flink的“Slot”是什么?它与并行度的关系是什么?
Slot是TaskManager中资源隔离的单元,代表一个固定大小的资源子集(主要是内存)。每个TaskManager可配置多个Slot(如taskmanager.numberOfTaskSlots: 4
)。
与并行度的关系:
- 每个Slot可运行一个或多个Task(属于不同算子),但同一算子的不同Task不能运行在同一Slot。
- 作业的总并行度受限于集群的总Slot数(总Slot = 所有TaskManager的Slot数之和)。
- 例如:集群总Slot为10,作业并行度最多为10;若作业并行度为8,则使用8个Slot。
Slot的作用:
- 资源隔离:避免不同作业/任务争夺资源。
- 资源共享:同一作业的不同算子Task可共享Slot,提高资源利用率。
10. 什么是Flink的“作业图(JobGraph)”“执行图(ExecutionGraph)”和“物理执行图(Physical Graph)”?三者的转换关系是什么?
-
作业图(JobGraph):客户端将用户代码转换的最初始图,包含算子(Operator)和它们之间的数据流,未考虑并行度。
- 由客户端生成,提交给JobManager。
-
执行图(ExecutionGraph):JobManager将JobGraph按并行度拆分后生成的图,包含并行化的任务(ExecutionVertex)和中间结果分区(IntermediateResultPartition)。
- 是JobGraph的并行化版本,用于调度和执行。
-
物理执行图(Physical Graph):任务在TaskManager上实际运行的图,包含具体的Task实例和物理数据传输链路。
- 由TaskManager根据ExecutionGraph部署后生成,反映实际运行状态。
转换关系:
用户代码 → JobGraph(客户端)→ ExecutionGraph(JobManager)→ 物理执行图(TaskManager)
11. Flink支持哪几种部署模式?各有什么特点?
Flink支持多种部署模式:
-
本地模式(Local):
- 特点:在单个JVM中运行,无需集群,适合开发和测试。
- 启动方式:
bin/start-cluster.sh local
-
standalone模式:
-
特点:Flink独立集群,不依赖外部资源管理器,部署简单,适合中小规模集群。
-
组件:包含JobManager、TaskManager和内部ResourceManager。
-
YARN模式:
- 特点:集成Hadoop YARN,由YARN管理资源,适合已有的Hadoop生态环境。
- 两种模式:Session模式(共享集群资源)和Per-Job模式(每个作业独占资源)。
-
Kubernetes(K8s)模式:
- 特点:容器化部署,支持弹性扩缩容,适合云原生环境。
- 优势:自动部署、故障自愈、资源隔离。
-
Mesos模式:
- 特点:适用于Mesos资源管理平台,较少使用。
12. 解释Flink中的“算子(Operator)”概念,常见的算子有哪些?
算子(Operator)是Flink中对数据进行转换处理的基本单元,接收一个或多个输入数据流,产生一个输出数据流。
常见算子:
-
转换算子(Transformation):
map
:对每个元素应用函数转换。filter
:根据条件过滤元素。flatMap
:将一个元素转换为多个元素。keyBy
:按key分组,将流转换为KeyedStream。reduce
:对KeyedStream进行聚合,生成单个结果。aggregations
:如sum
、min
、max
等聚合操作。
-
窗口算子(Window):
window
:基于时间或计数定义窗口。windowAll
:对整个流开窗(并行度为1)。apply
:对窗口内数据应用处理逻辑。
-
连接算子(Connection):
union
:合并多个同类型数据流。connect
:连接两个不同类型的数据流,保留各自类型。join
:基于条件关联两个数据流(通常在窗口中使用)。
-
输出算子(Sink):
print
:打印到控制台。writeAsText
:写入文本文件。addSink
:自定义输出(如写入Kafka、Elasticsearch)。
示例:使用多种算子
DataStream<String> input = env.socketTextStream("localhost", 9999);input.flatMap((String line, Collector<Tuple2<String, Integer>> out) -> {for (String word : line.split(" ")) {out.collect(new Tuple2<>(word, 1));}}).keyBy(tuple -> tuple.f0).timeWindow(Time.seconds(5)).sum(1).print();
13. Flink的“数据交换策略(Data Exchange Strategy)”有哪几种?分别适用于什么场景?
数据交换策略指算子之间的数据传输方式,决定了上游任务如何向下游任务发送数据。
常见策略:
-
Forward(转发):
-
特点:上游任务直接将数据发送给下游同并行度的任务(一对一)。
-
适用场景:
map
、filter
等无需重分区的算子,数据本地传输,效率高。 -
Shuffle(洗牌):
- 特点:上游任务将数据随机分配给下游所有任务。
- 适用场景:
groupBy
、reduce
等需要全局聚合的场景,会产生网络传输。
-
Broadcast(广播):
- 特点:上游任务将数据发送给下游所有任务(每个下游任务都接收完整数据)。
- 适用场景:小表关联(如将配置数据广播到所有任务)。
-
Key Group(按Key分组):
- 特点:根据Key的哈希值将数据发送到对应的下游任务(相同Key的数据进入同一任务)。
- 适用场景:
keyBy
后的算子(如sum
、window
),保证同一Key的数据被同一任务处理。
-
Rebalance(重平衡):
- 特点:上游任务通过轮询方式均匀分配数据到下游任务。
- 适用场景:数据倾斜时重新分配负载,平衡各任务压力。
14. 什么是Flink的“窗口(Window)”?为什么窗口是流处理中的核心概念?
窗口(Window)是流处理中将无限数据流分割为有限数据块进行处理的机制,是处理无界流的核心手段。
窗口的作用:
- 流数据是无限的,窗口将其划分为有限的“批”,便于进行聚合、关联等操作(如统计每5分钟的订单量)。
- 解决数据乱序问题,通过窗口等待延迟数据到达。
窗口类型:
-
时间窗口(Time Window):
- 滚动窗口(Tumbling Window):固定大小,无重叠(如每小时一个窗口)。
- 滑动窗口(Sliding Window):固定大小,有重叠(如每30分钟统计前1小时数据)。
- 会话窗口(Session Window):基于空闲时间划分,无活动时窗口关闭。
-
计数窗口(Count Window):
- 滚动计数窗口:达到指定数量的元素时触发(如每100个元素一个窗口)。
- 滑动计数窗口:每N个元素滑动一次,窗口包含M个元素(M > N)。
示例:滚动时间窗口
DataStream<Tuple2<String, Integer>> stream = ...;// 按Key分组,每5秒一个窗口,求和
stream.keyBy(tuple -> tuple.f0).timeWindow(Time.seconds(5)).sum(1).print();
15. Flink的“背压(Backpressure)”是什么?如何检测和处理背压问题?
背压指流处理中,下游算子处理速度慢于上游算子发送速度,导致数据在中间环节积压的现象。若不处理,可能导致内存溢出或作业崩溃。
检测背压:
- Flink Web UI:在“Job Graph”页面查看算子的“Backpressure”指标(OK/WARN/High)。
- Metrics:监控
backpressure.timeMsPerSecond
等指标。 - 日志:查看TaskManager日志中的“Backpressure detected”警告。
处理背压:
- 优化下游算子:提高处理效率(如减少复杂计算、使用更高效的数据结构)。
- 增加并行度:提高下游算子的并行度,提升整体处理能力。
- 调整Checkpoint:减少Checkpoint频率或优化状态存储(如使用RocksDB)。
- 限流:在Source端限制输入速度(如
env.setBufferTimeout(-1)
关闭缓冲)。 - 数据倾斜处理:若因数据倾斜导致部分任务背压,需均衡数据分布。
16. 简述Flink的“类型系统(Type System)”,为什么需要关注数据类型?
Flink的类型系统用于描述数据流中元素的数据类型,确保序列化、反序列化和状态管理的正确性。
核心类型:
- 基础类型:Integer、String、Double等Java基本类型及其包装类。
- 复合类型:Tuple(元组)、POJO(普通Java对象)、Enum(枚举)。
- 集合类型:List、Map、Array等。
- 特殊类型:Option、Either、GenericType等。
关注数据类型的原因:
- 序列化:Flink需将数据序列化后在网络传输或写入状态后端,类型信息确保序列化正确。
- 状态管理:状态存储依赖类型信息,错误的类型可能导致状态无法恢复。
- 性能优化:Flink对POJO等类型有特殊优化,使用合适的类型可提升性能。
示例:定义POJO类型(需满足无参构造函数、字段可见或有getter/setter)
public class User {private String name;private int age;// 无参构造函数public User() {}// getter和setterpublic String getName() { return name; }public void setName(String name) { this.name = name; }public int getAge() { return age; }public void setAge(int age) { this.age = age; }
}
17. Flink的“ExecutionConfig”有什么作用?可以配置哪些核心参数?
ExecutionConfig是Flink作业的执行配置对象,用于设置作业级别的执行参数,影响作业的性能和行为。
核心配置参数:
- 并行度:
setParallelism(int parallelism)
- 检查点模式:
setCheckpointingMode(CheckpointingMode mode)
- 状态后端:
setStateBackend(StateBackend backend)
- 自动类型注册:
enableAutoTypeRegistration(boolean enabled)
- 类加载器模式:
setClassLoader(ClassLoader classLoader)
- 优化器参数:如
setUseSnapshotCompression(boolean enable)
启用快照压缩。
示例:配置ExecutionConfig
ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
ExecutionConfig config = env.getConfig();// 设置默认并行度
config.setParallelism(4);// 启用类型自动注册
config.enableAutoTypeRegistration(true);// 配置状态后端为RocksDB
config.setStateBackend(new RocksDBStateBackend("hdfs:///flink/checkpoints"));
18. 什么是Flink的“动态缩放(Dynamic Scaling)”?其实现原理是什么?
动态缩放指在作业运行过程中调整算子的并行度,无需停止作业,以适应数据量变化(如峰值时增加并行度,低谷时减少)。
实现原理:
- 触发缩放:通过Flink CLI或REST API发起缩放请求,指定新的并行度。
- 生成Savepoint:Flink自动触发一次Savepoint,保存当前作业状态。
- 重启作业:基于Savepoint停止旧作业,以新并行度重启作业。
- 状态重分配:将原有状态按新并行度重新分配给新任务(基于Key的哈希值)。
限制:
- 仅支持有状态作业,且状态需可重分配(如Keyed State)。
- 无状态作业可直接缩放,无需Savepoint。
示例:动态调整并行度
# 动态将作业并行度调整为10
bin/flink scale <job-id> 10
19. 解释Flink中的“Watermark”机制,它如何解决数据乱序问题?
Watermark是Flink中用于处理乱序数据的机制,本质是一个时间戳,标识“小于该时间戳的事件已全部到达”,用于触发窗口计算。
工作原理:
- 生成Watermark:Source算子或自定义算子根据事件时间生成Watermark,通常设置为“当前最大事件时间 - 允许的延迟时间”。
- 传递Watermark:Watermark在数据流中传播,下游算子根据接收到的Watermark判断是否触发窗口。
- 触发窗口:当Watermark时间戳大于等于窗口结束时间时,触发窗口计算,处理窗口内所有数据。
解决乱序问题:
- 通过设置合理的延迟时间(如5秒),等待迟到的数据到达后再触发窗口。
- 对于超出Watermark的迟到数据,可通过
sideOutputLateData
收集到侧输出流处理。
示例:生成Watermark
DataStream<Event> stream = ...;DataStream<Event> withWatermarks = stream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor<Event>(Time.seconds(5)) {@Overridepublic long extractTimestamp(Event element) {return element.getEventTime(); // 提取事件时间}}
);// 处理迟到数据
OutputTag<Event> lateTag = new OutputTag<Event>("late-data"){};
SingleOutputStreamOperator<Result> result = withWatermarks.keyBy(...).timeWindow(Time.seconds(10)).sideOutputLateData(lateTag).apply(...);DataStream<Event> lateData = result.getSideOutput(lateTag);
20. Flink的“Exactly-Once”语义是如何保证的?依赖哪些核心机制?
Exactly-Once语义指数据在流处理中被精确处理一次,既不重复也不丢失,是流处理的最高一致性保证。
实现依赖的核心机制:
-
检查点(Checkpoint):
- 周期性快照算子状态和数据源偏移量,故障时可恢复到一致状态。
-
两阶段提交(2PC):
- 预提交(Pre-commit):各算子将状态写入临时存储,确认所有算子完成预提交。
- 提交(Commit):Checkpoint成功后,正式提交状态和数据源偏移量。
-
幂等性Sink:
- Sink算子支持幂等写入(如基于主键更新),即使重复写入也不会产生副作用。
-
可重放的数据源:
- 数据源支持从指定偏移量重放数据(如Kafka的offset),确保故障后可重新消费未处理的数据。
示例:Flink与Kafka结合实现Exactly-Once
// 配置Kafka消费者为Exactly-Once
Properties consumerProps = new Properties();
consumerProps.setProperty("bootstrap.servers", "localhost:9092");
consumerProps.setProperty("group.id", "test-group");
FlinkKafkaConsumer<String> consumer = new FlinkKafkaConsumer<>("input-topic",new SimpleStringSchema(),consumerProps
);
consumer.setStartFromEarliest();
consumer.setCommitOffsetsOnCheckpoints(true); // Checkpoint成功后提交offset// 配置Kafka生产者为Exactly-Once
Properties producerProps = new Properties();
producerProps.setProperty("bootstrap.servers", "localhost:9092");
FlinkKafkaProducer<String> producer = new FlinkKafkaProducer<>("output-topic",new KeyedSerializationSchemaWrapper<>(new SimpleStringSchema()),producerProps,FlinkKafkaProducer.Semantic.EXACTLY_ONCE // 启用Exactly-Once
);// 启用Checkpoint
env.enableCheckpointing(1000, CheckpointingMode.EXACTLY_ONCE);// 处理流程
env.addSource(consumer).map(...).addSink(producer);
二、100道Flink 面试题目录列表
文章序号 | Flink 100道 |
---|---|
1 | Flink面试题及详细答案100道(01-20) |
2 | Flink面试题及详细答案100道(21-40) |
3 | Flink面试题及详细答案100道(41-60) |
4 | Flink面试题及详细答案100道(61-80) |
5 | Flink面试题及详细答案100道(81-100) |