Flink基础
内容参考自:
有状态流式处理
概念
传统批次处理: 持续收集数据,以时间作为批次划分的依据,周期性执行批次运算,这样可能存在的场景问题:
- 假如一个小时作为一个批次划分的依据,需要统计特定事件转换次数,开始转换发生在第58分钟,结束转换在下一个小时的第7分钟,那么如何完成跨批次的数据统计?
- 数据从产生到被接收中间耗时不一定,可能某个事件发生早于A,但到达时间晚于A,如何处理这种接收到的时间顺序颠倒问题?
理想方法就是:
- 引入
状态(State)
机制,可以累积状态和维护状态,累积状态代表着过去历史中接受过的所有历史事件,对输出结果有影响 Time时间机制
: 有机制可以做到对数据完整性的操作,比如设定只有某个时间段上的数据全部都接收到后,再计算输出结果
这就是所谓的有状态流式处理
有状态流式处理的挑战
- 状态容错(State Fault Tolerance):
- 状态维护(State Management):
- Event-time处理 (Event-time processing):
- 状态保存与迁移(Savepoints and Job Migration):
状态容错
简单场景的精确一次(Exactly-once)容错保证:
无限流的数据进入,但后面是单一Process的计算,这种情况下如果要确保 Process 产生精确一次的状态容错,每处理完一笔数据,更改完状态后进行一次快照,快照包含在队列中并与相应的状态进行对比,完成一致的快照,就能确保精确一次
分布式状态容错
在分布式场景中,多个节点计算进行本地状态的修改,但只产生一个
Global consistent snapshot
(全域一致性的快照)基于
checkpoint
检查点机制进行容错恢复基于
simple lamport
演算法机制的延伸实现分布式快照
,Flink可以做到再不中断计算的状态下持续完成Global consistent snapshot
(全域一致性的快照)。大致方法就是Flink会在数据流中插入 checkpoint barrier标志位,后续的Operator在数据流中收到checkpoint barrier N后就会将自己的状态保存,这样从最开始的数据源到计算完成后都建立了这次的checkpoint保存状态,后面还有checkpoint barrier N+1、N+2也同时在数据流中同步进行,这样就可以做到在不阻挡运算的状况下持续地产生Checkpoint
状态维护
Flink目前支持的方式有:
JVM Heap存储状态
: 适合状态量不大的情况下,因为直接存储在JVM heap上,当需要读取状态时,是直接用Java object进行的读写,不需要序列化。但当 Checkpoint 需要将每一个运算值的本地状态放入 Distributed Snapshots 的时候,就需要进行序列化了RocksDB存储状态
: 一种 out of core 的状态后端。在 Runtime 的本地状态后端让使用者去读取状态的时候会经过磁盘,相当于将状态维护在磁盘里,与之对应的代价可能就是每次读取状态时,都需要经过序列化和反序列化的过程,性能可能相对来说差一点
Event-time处理
处理时间(Processing Time)
: Process Time 相当于事件到达然后开始进行处理的时间,是不一定的,比如网络原因这个时间都会变化事件时间(Event Time)
: Event Time 就是事件实际发生的时间,根据每一条处理记录所携带的时间戳来判定,这个是唯一且不变的接入时间(Ingestion Time)
: 是指事件在 source 运算符中进入 Flink 数据流的时间
对比
- Processing Time 处理起来更加的简单,而 Event Time 要更麻烦一些
- 使用 Processing Time 的时候,我们得到的处理结果(或者说流处理应用的内部状态)是不确定的。而因为 Flink 内部对 Event Time 做了各种保障,使用 Event Time 的情况下,无论重放数据多少次,都能得到一个相对确定可重现的结果
- 判断应该使用 Processing Time 还是 Event Time 的时候,可以遵循一个原则:当你的应用遇到某些问题要从上一个 checkpoint 或者 savepoint 进行重放,是不是希望结果完全相同。如果希望结果完全相同,就只能用 Event Time;如果接受结果不同,则可以用 Processing Time。Processing Time 的一个常见的用途是,我们要根据现实时间来统计整个系统的吞吐,比如要计算现实时间一个小时处理了多少条数据,这种情况只能使用 Processing Time
参考链接
状态保存与迁移
基于Savepoint机制实现,Savepoint跟checkpoint类似,不同在于Savepoint是手动触发用于全局状态保存的,具体参考链接:
Flink实时计算-深入理解 Checkpoint和Savepoint
Flink基本概念
Streams
: 流,分为有限数据流与无限数据流,unbounded stream
是有始无终的数据流,即无限数据流;而bounded stream
是限定大小的有始有终的数据集合,即有限数据流,二者的区别在于无限数据流的数据会随时间的推演而持续增加,计算持续进行且不存在结束的状态,相对的有限数据流数据大小固定,计算最终会完成并处于结束的状态。State
: 状态是计算过程中的数据信息,在容错恢复和 Checkpoint 中有重要的作用,流计算在本质上是 Incremental Processing,因此需要不断查询保持状态;另外,为了确保 Exactly- once 语义,需要数据能够写入到状态中;而持久化存储,能够保证在整个分布式系统运行失败或者挂掉的情况下做到 Exactly- once,这是状态的另外一个价值。Time
: 分为Event time
、Ingestion time
、Processing time
,Flink 的无限数据流是一个持续的过程,时间是我们判断业务状态是否滞后,数据处理是否及时的重要依据。API
: API 通常分为三层,由上而下可分为SQL / Table API
、DataStream API
、ProcessFunction
三层,API 的表达能力及业务抽象能力都非常强大,但越接近 SQL 层,表达能力会逐步减弱,抽象能力会增强,反之,ProcessFunction 层 API 的表达能力非常强,可以进行多种灵活方便的操作,但抽象能力也相对越小
Flink Window
- 以事件数量驱动的Count Window
- 以会话间隔驱动的Session Window
- 以时间驱动的Time Window