目录
1、背压问题
2、Flink是如何支持批流一体的
3、Flink任务延迟高,想解决这个问题,你会如何入手
4、Flink的监控页面,有了解吗,主要关注那些指标?
5、你们之前Flink集群规模有多大?部署方式是什么?你了解哪些部署方式?
6、Flink如何做压测和监控
7、Flink checkpoint 的相关查考?如何做checkpoint,如何监控,存储在哪里?等
8、Flink Savepoint 的相关查考?
9、Flink exactly-once 的保证?
10、Flink window、watermark、sideout?或者如何实现计算、乱序、延迟、容错?
11、Flink的时间语意支持?三种时间语义
12、Flink 重启策略?
13、Flink状态存储都有哪些?差异是什么?
14、Flink 是如何保证Exactly-once语义的?或者说保证的先决条件都有哪些?
15、Flink的内存管理?内存划分等等考察
16、Flink集群角色考察?
17、Flink中的Window出现了数据倾斜,你有什么解决办法?
18、Flink任务延迟高,想解决这个问题,你会如何入手?
19、 Flink 资源管理中 Task Slot 的概念?
20、Flink 的常用算子?Flink的开发模型?
21、Flink的并行度了解吗?Flink的并行度设置是怎样的?
22、Flink的状态存储后端都有哪些?差异是什么?你选用的是哪个?为什么?
23、Flink Operator Chains(算子链)是什么?为什么?
24、Flink 提供哪几类API?
25、Flink编程模型是什么?
26、讲一下Flink的运行架构,Flink集群有哪些角色?各自有什么作用?
27、Flink的集群部署模式有哪些?
28、Flink集群优化?
29、Flink 中对窗口的支持包括哪几种?说说他们的使用场景
30、Flink 的容错机制,Flink是如何做到容错的?
31、Flink分布式快照的原理是什么?
32、Flink中的Watermark机制
33、Flink是通过什么机制实现的背压机制?
34、Flink中的Window出现了数据倾斜,你有什么解决办法?
35、Flink中的Window出现了数据倾斜,你有什么解决办法?
36、FlinkSlots和并行度有什么关系?
37、Flink分层模型
38、Flink的执行图有哪几种?分别有什么作用
39、Flink的window作用?编程模型?
40、Flink的watermark作用?生成方式?
41、Flink 分布式快照的原理是什么
背压产生的原因
流量徒增,
流量内容异常,
如何发现背压
Flink web ui
采集到prometheus,报警发现
背问题的定位与处理
配置问题,GC的配置、内存&CPU的配置
代码问题,算子使用不合理
数据问题,数据倾斜,keyby热点key解决,随机后缀->打散处理->还原二次处理
在流处理引擎之上,Flink 有以下机制:
window+trigger,用于限制计算范围
watermark,解决乱序
Side Output和Allowed Lateness,解决late events
checkpoint+state,用于实现容错、有状态的处理;
在同一个流处理引擎之上,Flink 还存在另一套机制,用于实现高效的批处理
用于调度和恢复的回溯法:由 Microsoft Dryad 引入,现在几乎用于所有批处理器;
用于散列和排序的特殊内存数据结构:可以在需要时,将一部分数据从内存溢出到硬盘上;
优化器:尽可能地缩短生成结果的时间。
原因:定位tm、task、算子
解决办法:资源调优和算子调优
资源调优即是对作业中的Operator的并发数(parallelism)、CPU(core)、堆内存(heap_memory)等参数进行调优
作业参数调优包括:并行度的设置,State的设置,checkpoint的设置
监控页面指标分类
系统指标
作业的可用性,如 uptime (作业持续运行的时间)、fullRestarts (作业重启的次数)
作业的流量,如numRecordsIn、numBytesInLocal等相关指标来关注作业处理情况
作业的资源,如CPU、mem、GC、network等,这些指标一般是用来排查作业性能瓶颈
作业的状态,checkpoint 相关信息,checkpoint 的时长、checkpoint 的大小、作业失败后恢复的能力、成功和失败的 checkpoint 数目以及在 Exactly once 模式下 barrier 对齐时间
自定义指标
处理逻辑耗时埋点
外部服务调用的性能埋点
需要关注指标
作业状态,运行情况、重启情况、checkpoint情况、barrier对齐情况
作业性能,处理延迟、数据倾斜、性能瓶颈
业务逻辑,流量情况、上游数据质量、新上的逻辑是否存在问题、数据是否存在丢失
1、有多大?3000-5000cu 等等,按需回答即可
2、部署方式,session、perjob、application
3、部署方式差异,从任务和JM、TM、Client三者交互来回答
session 共用JM
per-job和session 需要客户端做三件事
获取作业所需的依赖项;
通过执行环境分析并取得逻辑计划,即StreamGraph→JobGraph;
将依赖项和JobGraph上传到集群中
application模式下,不共用JM,且客户端的三件事是JM来处理
压力测试主要体现在source 、代码、 sink 三个点
source的压测主要通过mock kafka数据,分为数据量、数据内容,特别在数据内容会可以制造数据倾斜来测试代码情况
代码层面,watermark大小和窗口大小来压测内存、state大小等
sink的压测主要是针对写入媒介的压力测试,比如ch的batch调整、kafka的batch 和 ack配置等
监控分为以下几类
基础监控,如JM、TM的cpu、mem负载之类的
软件监控,如checkpoint耗时、大小;数据流入流出量;背压等情况等
业务监控,即自定义埋点,如处理耗时,外部使用好事
7.1、底层核心算法:
Flink的Checkpoint机制原理来自“Chandy-Lamport algorithm”算法
7.2、checkpoint的组件:
Flink的JobManager为其创建一个 CheckpointCoordinator(检查点协调器),CheckpointCoordinator全权负责本应用的快照制作
7.3、checkpoint核心原理:
基于Chandy-Lamport 算法,实现了一个分布式一致性的存储快照算法
7.4、Flink中checkpoint执行流程
1、CheckpointCoordinator周期性的向该流应用的所有source算子发送barrier
2、当某个source算子收到一个barrier时,便暂停数据处理过程,然后将自己的当前状态制作成快照,并保存到指定的持久化存储中,最后向CheckpointCoordinator报告自己快照制作情况,同时向自身所有下游算子广播该barrier,恢复数据处理
3、下游算子收到barrier之后,会暂停自己的数据处理过程,然后将自身的相关状态制作成快照,并保存到指定的持久化存储中,最后向CheckpointCoordinator报告自身 快照情况,同时向自身所有下游算子广播该barrier,恢复数据处理
4、每个算子按照步骤3不断制作快照并向下游广播,直到最后barrier传递到sink算子,快照制作完成
5、当CheckpointCoordinator收到所有算子的报告之后,认为该周期的快照制作成功; 否则,如果在规定的时间内没有收到所有算子的报告,则认为本周期快照制作失败
7.5、Flink中checkpoint执行流程-简单版本(4个步骤,1566)
1、一个动作,向source发送barrier
2、五个动作,source接收barrier制作checkpoint,保存到持久化存储,向Coordinator汇报状态,向下游算子广播该barrier,自己恢复数据处理
3、六个动作,下游算子接收barrier,暂停数据处理过程,保存到持久化存储,向Coordinator汇报状态,向下游算子广播该barrier,自己恢复数据处理
4、动作重复,重复2中的6个动作,直到最后barrier传递到sink算子
5、判断状态,CheckpointCoordinator根据汇报信息决定是否checkpoint成功
7.6、当作业失败后,checkpoint如何恢复作业?
Flink提供了 应用自动恢复机制 和 手动作业恢复机制
应用自动恢复机制,定期恢复策略:fixed-delay、失败比率策略:failure-rate、直接失败策略:None 失败不重启
手动作业恢复机制,每通过Flink run 方式/页面提交方式恢复都会重新生成 jobId,Flink 提供了在启动之时通过设置 -s .参数指定检查点目录的功能,让新的 jobld 读取该检查点元文件信息和状态信息,从而达到指定时间节点启动作业的目的
7.7、如何判断checkpoint是否可以恢复失败的程序?
通常当作业执行失败、资源异常重启等非人为触发的异常场景时,支持
但是如果修改了作业的运算逻辑,作业的计算逻辑已发生更改,可能不支持
7.8、checkpoint恢复流程
首先客户端提供 Checkpoint 或 Savepoint 的目录
1、重启应用,JM 从给定的目录中找到 _metadata 文件(Checkpoint 的元数据文件)
2、JM 拿到所有算子对应的 State,给各个 subtask 分配 StateHandle(状态文件句柄)
3、TM 启动时,也就是 StreamTask 的初始化阶段会创建 KeyedStateBackend 和 OperatorStateBackend,TM从 checkpoint 中读取状态,将状态重置
4、开始消费并处理检查点到发生故障之间的所有数据
7.9、checkpoint如何监控(5类)(量、成、败、s、h)
Checkpoint counts:包含了触发、进行中、完成、失败、重置等状态数量统计。
lastest completed Checkpoint:记录了最近一次完成的Checkpoint信息,包括结束时间,端到端市场,状态大小等。
lastest faild Checkpoint:记录了最近一次失败的Checkpoint信息。
lastest savepoint:记录了最近一次savepoint触发的信息。
lastest restore:记录了最近一次重置操作的信息,包括从Checkpoint到savepoint两种数据中重置恢复任务。
7.10、checkpoint配置相关(5类)()
Checkpoint mode:标记Checkpoint是exactly once 还是 at least once的模式。
interval:Checkpoint触发的时间间隔,时间间隔越小意味着越频繁的Checkpoint。
timeout:Checkpoint触发超时时间,超过指定时间JobManager会取消当次Checkpoint,并重新启动新的Checkpoint。
minimum pause between Checkpoint:配置两个Checkpoint之间最短时间间隔,当上一次Checkpoint结束后,需要等待该时间间隔才能触发下一次Checkpoint,避免触发过多的Checkpoint导致系统资源被消耗。
persist Checkpoint externally:如果开启Checkpoint,数据将同时写到外部持久化存储中
7.11、checkpoint的状态后端及差异?
memory、fs、rocksdb
memory jvm堆上;fs 文件系统;rocksdb 本地rocksdb,支持增量
7.12、Flink 的 checkpoint 机制对比 spark 有什么不同和优势?
Spark Streaming 的 Checkpoint 仅仅是针对 Driver 的故障恢复做了数据和元数据的 Checkpoint
Flink 的 Checkpoint 机制要复杂了很多,它采用的是轻量级的分布式快照,实现了每个算子的快照,及流动中的数据的快照
savepoint恢复作业的限制都有那些?
有状态的算子增加,无影响,当你在作业中添加了一个算子后,该算子会被初始化为没有保存任何状态,新加入的算子则类似于无状态的算子
有状态的算子删除,有影响,allowNonReStoredSlale(short: -n)跳过无法恢复的算子
有状态算子顺序改变,可能有影响。如果你给这些算子赋予了独立的 ID,那么就不影响作业的恢复;如果你没有给算子赋予独立的 ID,通常算子进行重排序之后,系统分发的 ID 将会改变,这将会导致从保存点(savepoint)文件恢复失败
添加、删除、重排序无状态的算子,可能有影响。如果你给有状态的算子赋予了 ID,那么这些无状态的算子不会影响保存点(savepoint)的恢复;如果你没有给有状态的算子赋予 ID,对算子进行重排序之后有状态的算子的自动生成的 ID 会发生变化,这会导致从保存点(savepoint)恢复失败
总结一下Checkpoint和Savepoint的区别和联系?
checkpoint的侧重点是“容错”,而savepoint的侧重点是“维护”
savepoint是“通过checkpoint机制”创建的,所以savepoint本质上是特殊的checkpoint。
checkpoint面向Flink Runtime本身;savepoint面向用户
checkpoint的频率往往比较高。checkpoint的存储格式非常轻量级;savepoint则以二进制形式存储所有状态数据和元数据,执行起来比较慢而且“贵”。
checkpoint是支持增量的(通过RocksDB),savepoint不支持增量。
Flink实现端到端的exactly-once先决条件
source端支持数据重放。
Flink内部通过checkpoint保证。
sink端从故障恢复时,数据不会重复写入外部系统(幂等写入、事务写入)。
Checkpoint的核心?barrier+异步+增量
sink事务写入?
构建的事务对应着 checkpoint,等到 checkpoint 真正完成的时候,才把所有对应的结果写入 sink 系统中
实现方式,WAL可能会重复 vs 2PC 不丢不重,需要外部 sink 系统支持事务
1、window 解决计算的问题,将无限流转为有界流进行计算
2、watermark 解决 out of order的问题
3、sideoutput+allowed lateness 解决 late event的问题
4、checkpoint/savepoint+state来解决容错问题,分布式快照对的State存储状态进行备份
1. Event Time:这是实际应用最常见的时间语义,具体见文档第七章。
2. Processing Time:没有事件时间的情况下,或者对实时性要求超高的情况下。
3. Ingestion Time:存在多个 Source Operator 的情况下,每个 Source Operator
固定延迟重启策略(Fixed Delay Restart Strategy)
故障率重启策略(Failure Rate Restart Strategy)
没有重启策略(No Restart Strategy)
Fallback重启策略(Fallback Restart Strategy)
Flink 内存主要指 TaskManager 运行时提供的内存资源
TaskManager 主要由几个内部组件构成
Actor 系统,负责和 JobManager 等进程通信
IOManager,负责在内存不足时将数据溢写到磁盘和读回的
MemoryManager,负责内存管理的
TaskManager 的运行时 JVM heap划分
Network Buffers 区: 网络模块用于网络传输的一组缓存块对象,单个缓存块对象默认是32KB大小。Flink 会根据 TaskManager 的最大内存来计算该区大小,默认范围是64MB至1GB
Memory Manager 区: 用于为算子缓存运行时消息记录的大缓存池(比如 Sort、Join 这类耗费大量内存的操作),消息记录会被序列化之后存进这些缓存块对象。这部分区域默认占最大 heap 内存减去 Network Buffers 后的70%,单个缓存块同样默认是32KB
Free 区: 除去上述两个区域的内存剩余部分便是 Free heap,这个区域用于存放用户代码所产生的数据结构,比如用户定义的 State
Flink的序列化方式?重新造了一套轮子以定制数据的二进制格式
1、掌握了对序列化后的数据结构信息
2、提前优化序列化结构,极大地提高了性能
3、Flink 可以在作业执行之前确定对象的类型,并在序列化时利用这个信息进行优化
都有哪些角色?
JM,JM类似Master的角色,JM是Flink系统的协调者,它负责接收Flink Job,调度组成Job的多个Task的执行
TM,五个核心职责作业流的task执行、数据流处理(缓存+交换)、作业的状态管理、资源管理、故障管理;在TM中资源调度的最小单位是 task slot,task slot 的数量表示并发处理 task的数量,一个 task slot 中可以执行多个算子
Clint,该Client首先会对用户提交的Flink程序进行预处理,并提交到Flink集群中处理,所以Client需要从用户提交的Flink程序配置中获取JobManager的地址,并建立到JobManager的连接,将Flink Job提交给JobManager
Flink 任务提交流程?on yarn 模式为例
1、任务提交后,client向hdfs上传flink的jar包以及配置
2、解析命令参数项并初始化,-D&-t,向Yarn ResourceManager提交任务并申请资源
3、Yarn ResourceManager分配Container资源并启动ApplicationMaster
4、ApplicationMaster加载Flink的Jar包和配置构建环境,启动JM
5、ApplicationMaster根据JM配置向ResourceManager申请资源启动TM
6、NodeManager加载flink的jar包和配置环境启动TM
7、TM向JM发送心跳包、资源配置信息,等待JM向其分配任务
8、Client生成StreamGraph,再优化生成JobGraph发送给JM<非application mode>
9、JM接收JobGraph生成ExecutionGraph,JM会将ExecutionGraph分发给TM
10、TM根据ExecutionGraph部署任务,TM会根据ExecutionGraph生成Physical Graph
11、执行过程中TM上报信息,JM负责责监控作业状态、协调checkpoint
Flink client的作用?
获取作业所需的依赖项;
通过执行环境分析并取得逻辑计划,即StreamGraph→JobGraph;
将依赖项和JobGraph上传到集群中
Flink application mode 与非 application mode的差异?
JM是否共享 与 client的核心作用?
Flink中Graph的转变及哪些组件执行?
StreamGraph->JobGraph->ExecutionGraph->PhysicalGraph
StreamGraph->JobGraph在客户端(application mode 在JM端)
JobGraph->ExecutionGraph在JM端
ExecutionGraph->PhysicalGraph在TM端
Flink 资源划分情况了解?
每个TaskManager是一个JVM的进程, 可以在不同的线程中执行一个或多个子任务。
为了控制一个worker能接收多少个task。worker通过task slot来进行控制(一个worker至少有一个task slot)
原因:window产生数据倾斜指的是数据在不同的窗口内堆积的数据量相差过多
方案:在业务上规避这类问题&在数据进入窗口前做预聚合 & 重新设计窗口聚合的key
任务延迟的可能问题及解决
1、确定问题,如:Flink的哪个算子和task出现了反压
2、解决问题,如:业务+技术,技术层面:资源调优和算子调优
技术层面的调优都有哪些?
资源方面,如CPU、堆内存等参数进行调优。
作业参数调优包括:并行度的设置,State的设置,checkpoint的设置
TaskManager是实际负责执行计算的Worker,TaskManager 是一个 JVM 进程,并会以独立的线程来执行一个task或多个subtask。为了控制一个 TaskManager 能接受多少个 task,Flink 提出了 Task Slot 的概念
TaskManager会将自己节点上管理的资源分为不同的Slot:固定大小的资源子集。这样就避免了不同Job的Task互相竞争内存资源,但是需要主要的是,Slot只会做内存的隔离。没有做CPU的隔离
开发模型
1、构建ExecutionEnvironment
2、构建Source
3、Transformation转换操作
4、Sink输出结果
5、执行作业
常用算子
//Keyed Window
stream
.keyBy(...) <- 返回:KeyedStream
.window(...) <- 必选:窗口分配,根据实际业务指定具体窗口
[.trigger(...)] <- 选填:触发器,告诉窗口什么时候可以执行窗口函数(默认为默认实现)
[.evictor(...)] <- 可选:驱逐器,触发器触发后,在窗口函数执行前/后对数据操作(默认无)
[.allowedLateness(...)] <- 可选:指定允许延迟事件(默认为 0)
[.sideOutputLateData(...)] <- 可选:指定延迟事件的侧输出(默认无)
.reduce/aggregate/fold/apply() <- 必填:窗口函数,定义窗口的数据如何计算
[.getSideOutput(...)] <- 可选:DataStream.getSideOutput() 获取侧输出
//Non-Keyed Windows
stream
.windowAll(...) <- 必选:窗口分配,根据实际业务指定具体窗口
[.trigger(...)] <- 选填:触发器,告诉窗口什么时候可以执行窗口函数(默认为默认实现)
[.evictor(...)] <- 可选:驱逐器,触发器触发后,在窗口函数执行前/后对数据操作(默认无)
[.allowedLateness(...)] <- 可选:指定允许延迟事件(默认为 0)
[.sideOutputLateData(...)] <- 可选:指定延迟事件的侧输出(默认无)
.reduce/aggregate/fold/apply() <- 必填:窗口函数,定义窗口的数据如何计算
[.getSideOutput(...)] <- 可选:DataStream.getSideOutput() 获取侧输出
Flink分区策略?
GlobalPartitioner、ShufflePartitioner、RebalancePartitioner等等
Task*parallelism=subTask,subTask=slots
配置方式
1、配置文件默认,cat flink-conf.yaml |grep "parallelism.default"
2、env级别,env.setParallelism(5)
3、客户端级别,flink run -p 5
4、算子级别,env.addSource(kafkaConsumer).setParallelism(2);
配置优先级
从优先级上来看: 算子级别 > env级别 > Client级别 > 系统默认级别
Flink的Slot和parallelism有什么区别?
1.slot是静态的概念,是指taskmanager具有的并发执行能力
2.parallelism是动态的概念,是指程序运行时实际使用的并发能力
3.设置合适的parallelism能提高运算效率,太多了和太少了都不行
4.设置parallelism有多中方式,优先级为api>env>p>file
是什么?Flink会尽可能地将operator的subtask链接(chain)在一起形成task
为什么?是非常有效的优化:它能减少线程之间的切换,减少消息的序列化/反序列化,减少数据在缓冲区的交换,减少了延迟的同时提高整体的吞吐量
形成条件是什么?并行度、slot group、用户没有禁用 chain等等
DataSet API, 对静态数据进行批处理操作
DataStream API,对数据流进行流处理操作
Table API,对结构化数据进行查询操作,将结构化数据抽象成关系表
业务优化
配置优化,内存管理、任务调度、网络配置、状态管理
代码优化,算子,operator chain等
代码开发,5类,{tumbling、slide}*{time,count} + session
sql开发,
滚动窗口,TUMBLE(TABLE data, DESCRIPTOR(timecol), size)
滑动窗口,CUMULATE(TABLE data, DESCRIPTOR(timecol), step, size)
累积窗口,HOP(TABLE data, DESCRIPTOR(timecol), slide, size [, offset ])
保证flink在节点故障时,数据不丢不重且可恢复
核心能力,checkpoint+state
Checkpoint:是一种快照机制,它用于定期备份 Flink 程序中的状态,并将其存储在外部存储系统中
State:是 Flink 中的另一种重要机制,它用于存储计算过程中的中间状态。State 可以分为两种类型:Operator State 和 Keyed State
外部3个要求,内部barrier机制,结合一个核心算法实现
作用?解决out of order 问题,触发window计算。
原理?Watermark 的主要作用是确定事件时间窗口的边界,以便触发窗口计算。通过引入 Watermark,Flink 可以处理无序事件流(out-of-order events),Watermark越过窗口对应的window_end时,触发窗口关闭和计算
业务+技术配置+代码
业务+技术配置+代码
一个是组件的虚拟概念,一个是代码开发执行概念
Runtime层: Flink程序的最底层入口
DataStream/Dataset API层:这一层主要面向开发者
Table API:统一DataStream/DataSet API,抽象成带有Schema信息的表结构API
SQL:面向数据分析和开发人员,抽象为SQL操作,降低开发门槛和平台化
按照生成顺序分别为:StreamGraph-> JobGraph-> ExecutionGraph->物理执行图
StreamGraph,通过Stream API生成,这是执行图的最原始拓扑数据结构
JobGraph,StreamGraph在Client中经过算子chain链合并等优化,转换为JobGraph拓扑图,随后被提交到JobManager中
ExecutionGraph,JobManager中将JobGraph进一步转换为ExecutionGraph,此时ExecutuonGraph根据算子配置的并行度转变为并行化的Graph拓扑结构
物理执行图,比较偏物理执行概念,即JobManager进行Job调度,TaskManager最终部署Task的图结构
补充说明
StreamGraph到JobGraph的核心优化是:operator -> operator chain 减少数据在节点之间流动所需要的序列化/反序列化/传输消耗
ExecutionGraph是JobGraph的并行化版本,是调度层最核心的数据结
Client的三大核心作用
获取作业所需的依赖项;
通过执行环境分析并取得逻辑计划,即StreamGraph→JobGraph;
将依赖项和JobGraph上传到集群中
相对per-job模式和session模式,Application模式将三件事被转移到JobManager负责,Client只需要负责发起部署请求
核心作用:窗口是处理无限流的核心组件,窗口将无限的流分割为有限大小的“桶”,进而,可以对流进行计算
编程模型,Windows Assigner->Trigger->Evictor->Lateness->OutputTag->window process
Window Assigner,Tumbling Time Windows、Sliding Time Windows等
Trigger 即窗口触发器
trigger触发器接口有五个方法允许trigger对不同的事件做出反应
onElement()进入窗口的每个元素都会调用该方法。
onEventTime()事件时间timer触发的时候被调用。
onProcessingTime()处理时间timer触发的时候会被调用。
onMerge()有状态的触发器相关,并在它们相应的窗口合并时合并两个触发器的状态,例如使用会话窗口。
clear()该方法主要是执行窗口的删除操作
前三方法决定着如何通过返回一个TriggerResult来操作输入事件
CONTINUE:什么都不做。
FIRE:触发计算。
PURE:清除窗口的元素。
FIRE_AND_PURE:触发计算和清除窗口元素
Flink内置触发器
EventTimeTrigger基于事件时间和watermark机制来对窗口进行触发计算。
ProcessingTimeTrigger基于处理时间触发。
CountTrigger窗口元素数超过预先给定的限制值的话会触发计算
Evictor 即窗口剔除器,trigger 触发后、调用窗口函数之前或之后从窗口中删除元素
Allowed Lateness 即窗口容忍延迟时间
sideOutputLateData 即指定延迟事件的侧输出
window process - reduce/aggregate/process
作用?解决out of order 问题,触发window计算。
原理?Watermark 的主要作用是确定事件时间窗口的边界,以便触发窗口计算。通过引入 Watermark,Flink 可以处理无序事件流(out-of-order events),Watermark越过窗口对应的window_end时,触发窗口关闭和计算
核心算法:Chandy-Lamport算法
核心定义:持续创建分布式数据流及其状态的一致快照。
核心思想:在 input source 端插入 barrier,控制 barrier 的同步来实现 snapshot 的备份和 exactly-once 语义,1566