目录
25.window function 对数据的计算分为两类?
26.Flink 提供了 8 个 Process Function?
35.Flink+Kafka 如何实现端到端的 exactly-once 语义
57.检查点(checkpoint)和保存点(savepoint)的区别?
1.什么是flink?
ApacheFlink是一个框架和分布式处理引擎,用于对无界和有界数据流进行状态计算。
Flink能够提供毫秒级别的延迟,同时保证了数据处理的低延时,高吞吐和结果的正确性,还提供了丰富的时间类型和窗口计算,Exactly-once (就一次)语义支持,另外还可以进行状态管理,并提供了CEP(复杂事件处理)的支持。
2.sparktreaming 和 strom 有啥区别?
storm:实时,优点:良好的容错性,事务;并且是单一的框架
sparkString:批处理,准实时,一个一个的batch,一个batch就是一个时间段内连续不间断的rdd。
3.flink 和 sparktreaming 有啥区别?
- 数据模型
spark采用RDD模型,spark streaming的DStream实际上也就是一-组 组小批数据RDD的集合。
flink基本数据模型是数据流,以及事/件序列。
- 运行架构
是批计算,将DAG划分为不同的stage,一个完成后才可以计算下一个。
flink是标准的流执行模式,一个事件在一个节点处理完后可以直接发往下一个节点进行处理。
4.Flink 的重要特点?
- 事件驱动型:事件驱动型应用是一类具有状态的应用,它从一个或多个事件来提取数据,并根据到来的时间触发计算,状态更新或其他外部动作。
- 基于流的世界观:在flink的世界观中,一切都是由流组成的,离线数据是有界限的流,实时数据是一个没有界限的流,这就是所谓的有界流和无界流。
- 分层的API:越顶层越抽象,表达含义越简明,使用越方便。越底层越方便,表达意思越丰富,使用越灵活。
5.什么是有界流和无界流?
在Spark的世界观中,一切都是由批次组成的,离线数据是一个大批次,而实时数据是一个一个无限的小批次组成的。
在Flink的世界观中,一切都是由流组成的,离线数据是有界限的流,实时数据是一个没有界限的流,这就是有界流和无界流。
- 无界数据流:
有定义流的开始,但没有定义流的结束。它们会无休止地产生数据。
无界流的数据必须持续处理,即数据被摄取后需要立刻处理。我们不能等到所有数据都到达再处理,因为输入是无限的,在任何时候输入都不会完成。
处理无界数据通常要求以特定顺序摄取事件,例如事件发生的顺序,以便能够推断结果的完整性。
- 有界数据流:
有定义流的开始,也有定义流的结束。
有界流可以在摄取所有数据后再进行计算。
有界流所有数据可以被排序,所以并不需要有序摄取。
有界流处理通常被称为批处理
6.Flink的其他特点?
- 支持事件时间(event- time)和处理时间(processing time)
- 精确一次的状态一致性保证
- 低延迟,每秒处理数百万个事件,毫秒级延迟
- 与众多常用存储系统的连接
- 高可用,动态扩展,实现7*24小时全天候运行
7.Flink 组件?
jobManager:作业管理器
taskManager:任务管理器
resourceManager:资源管理器
dispacher:分发器
8.jobManager作用?
- 控制一个应用程序执行的主进程,也就是说,每个应用程序都会被一个不同的jobManager所控制。
- jobManager会先接收到要执行的应用程序,这个应用程序会包括:作业图,逻辑数据流图和打包了所有类、库和其它资源的jar包。
- jobManager会把jobGraph转换成一个物理层面的数据流图,这个图被叫做“执行图”,包含了所有可以执行的任务。
- jobManager会向资源管理器(resourceManager)请求执行任务必要的资源,也就是任务管理器(taskManager)上的插槽(slot)。一旦它获取到了足够的资源,就会将执行图分发到真正运行它们的taskManager上。而在运行过程中,jobManager会负责所有需要中央协调的操作,比如说检查点(checkpoints)的协调。
9.jobManager收到的应用程序包含哪些?
作业图(JobGraph),逻辑数据流图(logic dataflow graph)和打包了所有类、库和其它资源的jar包。
10.taskManager作用?
flink中的工作进程。通常在flink中会有多个taskManager运行,每一个taskManager都包含了一定数量的插槽(slots)。插槽的数量限制了taskManager能够执行的任务数量。
启动之后,taskManager会向资源管理器注册它的插槽;收到资源管理器的指令后,taskManager就会将一个或多个插槽提供给jobManager调用。jobManager就可以向插槽分配任务(tasks)来执行了。
在执行过程中,一个taskManager可以跟其他运行同一应用程序的taskManager交换数据。
11.taskManager执行任务的数量由什么来决定的?
task的数量由taskManager内包含的slots的总数量决定,slot的总数量也决定了任务执行的并行度。
12.resourceManager作用?
主要负责管理任务管理器(taskManager)的插槽(slot),taskManager插槽是flink中定义的处理资源单元。
flink为不同的环境和资源管理工具提供不同的资源管理工具,比如YARN、Mesos、K8s,以及standalone部署。
当jonManager申请插槽资源时,ResourceManager会将有空间插槽来满足jobManager的请求,它还可以向资源提供平台发起会话,以提供启动taskManager进程的容器。
13.flink的资源单元?
taskManager的slot
14.分发器的作用?
- 可以跨作业运行,它为应用提交提供了REST接口。
- 当一个应用被提交执行时,分发器就会启动并将应用移交给一个jobManager
- dispatcher也会启动一个web UI,用来方便地展示和监控作业执行的信息
- dispatcher在架构中可能并不是必须的,这个取决于应用提交运行的方式
15.总结任务提交流程?
Flink 任务提交后, Client 向 HDFS 上传 Flink 的 Jar 包和配置, 之后向 Yarn ResourceManager 提交任务, ResourceManager 分配 Container 资源并通知对应的NodeManager 启动 ApplicationMaster, ApplicationMaster 启动后加载 Flink 的 Jar 包和配置构建环境,然后启动 JobManager,之后 ApplicationMaster 向 ResourceManager 申 请 资 源 启 动 TaskManager , ResourceManager 分 配 Container 资 源 后 , 由ApplicationMaster 通 知 资 源 所 在 节 点 的 NodeManager 启 动 TaskManager , NodeManager 加载 Flink 的 Jar 包和配置构建环境并启动 TaskManager,TaskManager 启动后向 JobManager 发送心跳包, 并等待 JobManager 向其分配任务。
16.flink的应用程序包含几部分?
- 所有的flink程序都是由三部分的:source、Transformation和Sink
- source负责读取数据源,Transformation利用各种算子进行处理加工,Sink负责输出
17.flink的执行图分为几层?分别什么作用?
StreamGraph -> JobGraph -> ExecutionGraph -> 物理执行图
- StreamGraph:是根据用户通过 Stream API 编写的代码生成的最初的图。用来表示程序的拓扑结构。
- JobGraph:StreamGraph经过优化后生成JobGraph,提交给JobManager的数据结构。主要优化为,将多个符合条件的节点chain(链)在一起作为一个节点。
- ExecutionGraph:JobManager根据JobGraph生成ExecutionGrouph。ExectionGrouph是JobGrouph的并行化版本,是调度层最核心的数据结构
- 物理执行图:JobManager根据ExectionGrouph对Job进行调度后,在各个taskManager上部署task后形成的“图”,并不是一个具体的数据结构。
18.算子之间数据传输的形式?
- One-to-one:stream维护者分区以及元素的顺序(比如source和map之间)。这就意味着map算子的子任务看到的元素的个数以及顺序跟source算子的子任务生产的元素的个数、顺序相同。map、fliter、flatmap、等算子都是one-to-one的对应关系。
- Redistributing:stream的分区会发生改变。每一个算子的子任务依据所选择的transformation发送数据到不同的目标任务。例如:keyBy基于hashCode重分区、而broadcast和rebalance会随即重新分区,这些算子都会引起redistribute过程,而redistribute过程就类似于spark中的shuffle过程。
19.flink的任务链? 任务链的要求?
- flink的任务链:
flink采用了一种称为任务链的优化技术,可以在特定的条件下减少本地雍熙的开销。为了满足任务链的要求,必须将两个或者多个算子设为相同的并行度,并通过本地转发(local forward)的方式进行连接
相同并行度的 one-to-one操作,flink这样相连的算子链接在一起形成一个task,原来的算子成为里面的subtask
并行度相同、并且是one-to-one操作,两个条件缺一不可
- 任务链的要求:
并行度相同、并且是one-to-one操作,两个条件缺一不可
20.flink的切分流和选择流?
选择流:
SplitStream→DataStream:从一个 SplitStream 中获取一个或者多个 DataStream。Select 就是获取分流后对应的数据
需求:传感器数据按照温度高低(以 30 度为界),拆分成两个流。
切分流:
DataStream → SplitStream:根据某些特征把一个 DataStream 拆分成两个或者多个 DataStream。
21.flink连接流和合并流的区别?
- Union 之前两个流的类型必须是一样, Connect 可以不一样,在之后的 coMap中再去调整成为一样的。
- Connect 只能操作两个流, Union 可以操作多个。
22.flink里面的rich函数?
“ 富函数” 是 DataStream API 提供的一个函数类的接口, 所有 Flink 函数类都有其 Rich 版本。它与常规函数的不同在于, 可以获取运行环境的上下文, 并拥有一些生命周期方法, 所以可以实现更复杂的功能。
- RichMapFunction
- RichFlatMapFunction
- RichFilterFunction
- …
- Rich Function 有一个生命周期的概念。典型的生命周期方法有:
- open()方法是 rich function 的初始化方法,当一个算子例如 map 或者 filter
- 被调用之前 open()会被调用。
- close()方法是生命周期中的最后一个调用的方法,做一些清理工作。
- getRuntimeContext()方法提供了函数的 RuntimeContext 的一些信息,例如函数执行的并行度,任务的名字,以及 state 状态。
23.flink的window分为几种?
(1) TimeWindow
- Tumbling Window (滚动窗口)
- Sliding Window (滑动窗口)
- Session Window (会话窗口)
(2) Count Window(计数窗口)
- 滑动计数窗口
- 滚动计数窗口
(3) 全局窗口
- Global Window (全局窗口)
24.time window分为?
Tumbling Window (滚动窗口)
Sliding Window (滑动窗口)
Session Window (会话窗口)
25.window function 对数据的计算分为两类?
- 增量聚合函数(incremental aggregation functions)
每条数据到来就进行计算,保持一个简单的状态
ReduceFunction, AggregateFunction
- 全窗口函数(full window functions)
先把窗口所有数据收集起来,等到计算的时候会遍历所有数据
ProcessWindowFunction
26.Flink 提供了 8 个 Process Function?
ProcessFunction
KeyedProcessFunction
CoProcessFunction
ProcessJoinFunction
BroadcastProcessFunction
KeyedBroadcastProcessFunction
ProcessWindowFunction
ProcessAllWindowFunction
27.Flink 的 TimerService?
1.currentProcessingTime(): Long 返回当前处理时间currentWatermark(): Long 返回当前 watermark 的时间戳
2.registerProcessingTimeTimer(timestamp: Long): Unit 会注册当前 key 的processing time 的定时器。当 processing time 到达定时时间时, 触发 timer。
3.registerEventTimeTimer(timestamp: Long): Unit 会注册当前 key 的 event time 定时器。当水位线大于等于定时器注册的时间时, 触发定时器执行回调函数。
4.deleteProcessingTimeTimer(timestamp: Long): Unit 删除之前注册处理时间定 时器。如果没有这个时间戳的定时器, 则不执行。
5.deleteEventTimeTimer(timestamp: Long): Unit 删除之前注册的事件时间定时器, 如果没有此时间戳的定时器, 则不执行。
当定时器 timer 触发时, 会执行回调函数 onTimer()。注意定时器 timer 只能在keyed streams 上面使用。
28.Flink 为算子状态提供三种基本数据结构?
- 列表状态(List state)将状态表示为一组数据的列表。
- 联合列表状态(Union list state)也将状态表示为数据的列表。它与常规列表状态的区别在于,在发生故障时,或者从保 存点(savepoint)启动应用程序时如何恢复。
- 广播状态(Broadcast state)如果一个算子有多项任务,而它的每项任务状态又都相同,那么这种特殊情况最适合应 用广播状态。
29.Flink有两种类型的状态?键控状态特点?
- 算子状态( operator state)
算子状态的作用范围限定为算子任务
- 键控状态( keyed state)
键控状态特点?
根据输入数据流中定义的键(key) 来维护和访问
键控状态是根据输入数据流中定义的键(key) 来维护和访问的
Flink为每个key维护一一个状态实例,并将具有相同键的所有数据,都分区到同一个算子任务中,这个任务会维护和处理这个key对应的状态
当任务处理一条数据时, 它会自动将状态的访问范围限定为当前数据的key
30.Flink 状态一致性的级别?
AT-MOST-ONCE (最多一次)
当任务故障时,最简单的做法是什么都不干,既不恢复丢失的状态,也不重 播丢失的数据。At-most-once 语义的含义是最多处理一次事件。
AT-LEAST-ONCE (至少一次)
在大多数的真实应用场景,我们希望不丢失事件。这种类型的保障称为at- least-once,意思是所有的事件都得到了处理,而一些事件还可能被处理多次。
EXACTLY-ONCE (精确一次)
恰好处理一次是最严格的保证,也是最难实现的。恰好处理一次语义不仅仅意味着没有事件丢失,还意味着针对每一个数据, 内部状态仅仅更新一次。
31.Flink 什么是端到端的一致性?
目前我们看到的一致性保证都是由流处理器实现的,也就是说都是在Flink流处理器内部保证的;而在真实应用中,流处理应用除了流处理器以外还包含了数据源(例如Kafka)和输出到持久化系统
端到端的一致性保证,意味着结果的正确性贯穿了整个流处理应用的始终;每一个组件都保证了它自己的一-致性
整个端到端的一致性级别取决于所有组件中-一致性最弱的组件
32.端到端的一致性具体可以划分?
- 内部保证 —— 依赖 checkpoint
- source 端 —— 需要外部源可重设数据的读取位置
- sink 端 —— 需要保证从故障恢复时, 数据不会重复写入外部系统而对于 sink 端, 又有两种具体的实现方式: 幂等( Idempotent) 写入和事务性( Transactional) 写入。
33.sink端保证一致性的两种方式?
- 幂等写入:所谓幂等操作, 是说一个操作,可以重复执行很多次, 但只导致一次结果更改, 也就是说, 后面再重复执行就不起作用了。
- 事务写入:需要构建事务来写入外部系统,构建的事务对应着 checkpoint,等到 checkpoint,真正完成的时候, 才把所有对应的结果写入 sink 系统中。
34.事务性写入具体又有两种实现方式?
预写日志( WAL) 和两阶段提交( 2PC)。DataStream API 提供了 GenericWriteAheadSink 模板类和TwoPhaseCommitSinkFunction 接口, 可以方便地实现这两种方式的事务性写入
35.Flink+Kafka 如何实现端到端的 exactly-once 语义
- 第一条数据来了之后,开启一个kafka的事务(transaction) ,正常写入kafka分区日志但标记为未提交,这就是“预提交”
- jobmanager触发checkpoint操作,barrier 从source开始向下传递,遇到barrier的算子将状态存入状态后端,并通知jobmanager
- sink连接器收到barrier,保存当前状态,存入checkpoint,通知jobmanager,并开启下一阶段的事务,用于提交下个检查点的数据
- jobmanager收到所有任务的通知,发出确认信息,表示checkpoint完成
- sink任务收到jobmanager的确认信息,正式提交这段时间的数据
- 外部kafka关闭事务,提交的数据可以正常消费了。
36.flink StateBackend?
每传入一条数据,有状态的算子任务都会读取和更新状态
由于有效的状态访问对于处理数据的低延迟至关重要,因此每个并行任务都会在本地维护其状态,以确保快速的状态访问
状态的存储、访问以及维护,由一个可插入的组件决定,这个组件就叫做状态后端(state backend)
37.几种状态后端的区别?
- MemoryStateBackend
内存级的状态后端,会将键控状态作为内存中的对象进行管理,将它们存储在TaskManager的JVM堆上,而将checkpoint存储在JobManager的内存中
特点:快速、低延迟,但不稳定
- FsStateBackend
将checkpoint存到远程的持久化文件系统(FileSystem) 上,而对于本地状态,跟MemoryStateBackend一 样,也会存在TaskManager的JVM堆上
同时拥有内存级的本地访问速度,和更好的容错保证
- RocksDBStateBackend
将所有状态序列化后,存入本地的RocksDB中存储。
38.spark DAG 如何划分stage?
-
对于窄依赖,partition的转换处理在stage中完成计算,不划分(将窄依赖尽量放在在同一个stage中,可以实现流水线计算)。
-
对于宽依赖,由于有shuffle的存在,只能在父RDD处理完成后,才能开始接下来的计算,也就是说需要要划分stage(出现宽依赖即拆分)。
-
stage的切割规则:从后向前,遇到宽依赖就切割stage。
39.flink的资源管理器有哪些?
flink为不同的环境和资源管理工具提供不同的资源管理工具,比如YARN、Mesos、K8s,以及standalone部署。
40.flink 是否允许任务共享slot?
默认情况下,flink允许子任务共享slot,即使它们是不同的子任务。这样的结果是,一个slot可以保存作业的整个管道。
41.什么是并行度?
一个特定算子的子任务(subtask)的个数被称之为其并行度(parallelism)。一个程序中,不同的算子可能具有不同的并行度。
42.什么是stream最大并行度?
一般情况下,一个stream的并行度,可以认为就是其所有算子中最大的并行度。
43.flink的数据类型?
-
基础数据类型 :Flink支持所有的Java和Scala基础数据类型,Int, Double, Long, String, …
-
Java和Scala元组(Tuples)
-
Scala样例类(case classes)
-
Java简单对象(POJOs)
-
其它(Arrays, Lists, Maps, Enums, 等等) Flink对Java和Scala中的一些特殊目的的类型也都是支持的,比如Java的ArrayList,HashMap,Enum等等。
44.flink 的时间语义?
Event Time:事件创建的时间
Ingestion Time:数据进入Flink的时间
Processing Time:执行操作算子的本地系统时间,与机器相关
45.乱序数据有什么影响?
-
当Flink 以Event Time模式处理数据流时,它会根据数据里的时间戳来处理基于时间的算子
-
由于网络、分布式等原因,会导致乱序数据的产生
-
乱序数据会让窗口计算不准确
46.什么是watermark?
-
Watermark是一种衡量Event Time进展的机制,可以设定延迟触发
-
Watermark是用于处理乱序事件的,而正确的处理乱序事件,通常用Watermark机制结合window来实现;
-
数据流中的Watermark用于表示timestamp小于Watermark的数据,都已经到达了,因此,window的执行也是由Watermark触发的。
-
watermark用来让程序自己平衡延迟和结果正确性
47.watermark的特点?
-
watermark是一条特殊的数据记录
-
watermark必须单调递增,以确保任务的事件时间时钟在向前推进,而不是在后退
-
watermark与数据的时间戳相关
48.键控状态的数据结构?
-
值状态(Value state)
将状态表示为单个的值
-
列表状态(List state)
将状态表示为一组数据的列表
-
映射状态(Map state)
将状态表示为一-组Key-Value对
-
聚合状态(Reducing state & Aggregating State)
将状态表示为一个用于聚合操作的列表
49.什么是状态后端?
-
每传入一条数据,有状态的算子任务都会读取和更新状态
-
由于有效的状态访问对于处理数据的低延迟至关重要,因此每个并行任务都会在本地维护其状态,以确保快速的状态访问
-
状态的存储、访问以及维护,由一个可插入的组件决定,这个组件就叫做状态后端(state backend)
50.后端的职责?
状态后端主要负责两件事:
1)本地的状态管理;
2)将检查点(checkpoint)状态写入远程存储。
51.状态后端的类型?
-
MemoryStateBackend
内存级的状态后端,会将键控状态作为内存中的对象进行管理,将它们存储在TaskManager的JVM堆上,而将checkpoint存储在JobManager的内存中
特点:快速、低延迟,但不稳定
-
FsStateBackend
将checkpoint存到远程的持久化文件系统(FileSystem) 上,而对于本地状态,跟MemoryStateBackend一 样,也会存在TaskManager的JVM堆上
同时拥有内存级的本地访问速度,和更好的容错保证
-
RocksDBStateBackend
将所有状态序列化后,存入本地的RocksDB中存储。
52.什么是processfunction 函数?
- ProcessFunction是一个低阶的流处理操作,它可以访问流处理程序的基础构建模块:
事件(event)(流元素)
状态(state)(容错性,一致性, 仅在keyed stream中)
定时器(timers)(event time和processing time,仅在keyed stream中)
- ProcessFunction可以看作是一个具有keyed state和timers访问权的FlatMapFunction
通过RuntimeContext访问keyed state
计时器允许应用程序对处理时间和事件时间中的更改作出响应。对processElemet...)函 数的每次调用都获得一个Context对象,该对象可以访问元素的event time timestamp和TimerService
TimerService'可用于为将来的event/process time瞬 间注册回调。当到达计时器的特定时间时,将调用onT1imer...)方法。在该调用期间,所有状态都再次限定在创建计时器时使用的键的范围内,从而允许计时器操作键控状态
53.什么是侧输出流?
Flink 处理数据流时,我们经常会遇到这种情况:在处理一个数据源时,往往需要将该数据源中的不同类型的数据做分割处理,如果使用filter算子对数据源进行筛选分割的话,势必会造成数据流的多次复制,造成不必要的性能浪费;
Flink中的侧输出就是将数据流进行分割,而不对流进行复制的一种分流机制,flink的侧输出的另一个作用就是对延时迟到的数据进行处理,这样就可以不必丢弃迟到的数据。
案例:假设我们的需求是实时的从kafka接收生产数据,我们需要对迟到超过一定时长的数据进行另行处理。
54.flink 故障恢复机制的核心?
有状态流应用的一致检查点,其实就是所有任务的状态,在某个时间点的一份拷贝(一 份快照) ;这个时间点,应该是所有任务都恰好处理完一个相同的输入数据的时候
55.如何从检查点恢复状态?
-
在执行流应用程序期间,Flink 会定期保存状态的一致检查点
-
如果发生故障,Flink 将会使用最近的检查点来一致恢复应用程序的状态,并重新启动处理流程
-
遇到故障之后,第一步就是重启应用
-
第二步是从checkpoint中读取状态,将状态重置
从检查点重新启动应用程序后,其内部状态与检查点完成时的状态完全相同
-
第三步:开始消费并处理检查点到发生故障之间的所有数据
这种检查点的保存和恢复机制可以为应用程序状态提供"精确一次"(exactly-once)的一致性,因为所有算子都会保存检查点并恢复其所有状态,这样一来所有的输入流就都会被重置到检查点完成时的位置
56.什么是保存点?
-
Flink还提供了可以自定义的镜像保存功能,就是保存点(savepoints)
-
原则上,创建保存点使用的算法与检查点完全相同,因此保存点可以认为就是具有一些额外元数据的检查点
-
Flink不会自动创建保存点,因此用户(或者外部调度程序)必须明确地触发创建操作
-
保存点是一一个强大的功能。除了故障恢复外,保存点可以用于:有计划的手动备份,更新应用程序,版本迁移,暂停和重启应用,等等
57.检查点(checkpoint)和保存点(savepoint)的区别?
-
checkpoint的侧重点是“容错”,即Flink作业意外失败并重启之后,能够直接从早先打下的checkpoint恢复运行,且不影响作业逻辑的准确性。而savepoint的侧重点是“维护”,即Flink作业需要在人工干预下手动重启、升级、迁移或A/B测试时,先将状态整体写入可靠存储,维护完毕之后再从savepoint恢复现场。
-
savepoint是“通过checkpoint机制”创建的,所以savepoint本质上是特殊的checkpoint。
-
checkpoint面向Flink Runtime本身,由Flink的各个TaskManager定时触发快照并自动清理,一般不需要用户干预;savepoint面向用户,完全根据用户的需要触发与清理。
-
checkpoint的频率往往比较高(因为需要尽可能保证作业恢复的准确度),所以checkpoint的存储格式非常轻量级,但作为trade-off牺牲了一切可移植(portable)的东西,比如不保证改变并行度和升级的兼容性。savepoint则以二进制形式存储所有状态数据和元数据,执行起来比较慢而且“贵”,但是能够保证portability,如并行度改变或代码升级之后,仍然能正常恢复。
-
checkpoint是支持增量的(通过RocksDB),特别是对于超大状态的作业而言可以降低写入成本。savepoint并不会连续自动触发,所以savepoint没有必要支持增量。
58.flink和kafka端到端状态一致性的保证?
-
内部 -- 利用checkpoint机制,把状态存盘,发生故障的时候可以恢复,保证内部的状态一致性
-
source -- kafka consumer作为source,可以将偏移量保存下来,如果后续任务出现了故障,恢复的时候可以由连接器重置偏移量,重新消费数据,保证一致性
-
sink-- kafka producer作为sink,采用两阶段提交sink,需要实现一个TwoPhaseCommitSinkFunction
59.什么是2PC?
就是两阶段提交(Two-Phase-Commit)
-
对于每个checkpoint, sink 任务会启动一个事务,并将接下来所有接收的数据添加到事务里
-
然后将这些数据写入外部sink系统,但不提交它们--这时只是"预提交")
-
当它收到checkpoint完成的通知时,它才正式提交事务,实现结果的真正写入
这种方式真正实现了exactly-once,它需要一个提供事 务支持的外部sink系统。Flink 提供了TwoPhaseCommitSinkFunction接口。