Flink四大核心组件:State、Checkpoint、Window、Time

Flink四大核心组件:State、Checkpoint、Window、Time

1.state

1.1.状态管理:

flink有两种状态:keyedState和operatorState

state keyedState operatorState
支持的算子 keyedState只能用在keyedStream的算子中每个key对应一个state 可以用于所有算子常用于source,例如:FlinkKafkaConsumer
key和state 一个operator实例处理多个key,访问相应的多个state并发改变,State随着key在实例中迁移 一个operator实例对应一个state并发改变时,有多种重新分配方式可选:1.均匀分配 ;2.合并后每个得到全量
接口实现 通过runcontext访问:RichFunction 实现CheckPointed接口或ListCheckPointed接口
支持的数据结构 valueState,ListState,ReducingState,AggregatingState,MapState ListState

KeyedState 和 OperatorState 都有两种形式存在:
1、原始状态 RawState
原始状态,是由用户自行管理状态具体的数据结构,框架在做 checkpoint 的时候,使用 byte[]来读写内容,对其内部数据结构一无所知
2、托管状态 ManagedState
托管状态是由 Flink 框架管理的状态
通常,在 DataStream 上的状态,推荐使用托管的状态,当实现一个用户自定义的 Operator的时候,会使用到原始状态

RawState ManagedState
状态管理方式 用户自己管理 需要自己序列化 FlinkRuntime管理 自动存储,自动恢复 内存管理上有优化
状态数据结构 字节数组:byte[] 已知的数据结构:value,map,list…
推荐使用场景 自定义operator时可使用 大多数情况下均可使用

2.Checkpoint

2.1. 状态的保存和修复

checkpoint
定时制作分布式快照,对程序中的状态进行备份
发生故障时:
将整个作业的所有task都回滚到最后一次成功checkpoint中的状态,然后从那个点开始处理
必要条件:
数据源支持重发
一致性语义:
恰好一次
至少一次
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); env.enableCheckpointing(1000);
env.getCheckpointConfig().setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE);
env.getCheckpointConfig().setMinPauseBetweenCheckpoints(500); env.getCheckpointConfig().setCheckpointTimeout(60000); env.getCheckpointConfig().setMaxConcurrentCheckpoints(1); env.getCheckpointConfig().enableExternalizedCheckpoints(ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION);

2.2. 可选择的状态存储方式

state 的store和checkpoint的位置取决于stateBackend的配置
MemoryStateBackend
  state的数据保存在java的堆内存中,执行checkpoint的时候,会把state快照的数据保存到jobManager的内存中
基于内存的,生产环境不建议使用
FsStateBackend
  state的数据保存在taskManager的内存中,执行checkpoint的时候,会把state的快照数据保存到配置的文件系统中,可以使用HDFS等文件系统
RocksDBStateBackend
  在本地文件系统中维护一个状态,state会直接写入本地RockDb中,同时他需要配置一个远端的filesystem uri(一般是HDFS),在做checkpoint的时候,会把本地的数据直接复制到filesystem中,fail over的时候从filesystem中恢复到本地.
RockDB克服了state受内存限制的缺点,同时又能持久化到远端的文件系统中,适合在生产场景使用。

状态存储方式 MemoryStateBackend FsStateBackend RocksDBStateBackend
构造方法 MemoryStateBackend(int maxStateSize,boolean asynchronousSnapshots ) FsStateBackend(URI checkpointDataUri,boolean asynchronousSnapshots ) RockDBStateBackend(URI checkpointDataUri,boolean asynchronousSnapshots )
存储方式 State:TaskManager内存Checkpoint:JobManager内存 state:TaskManager内存Checkpoint:外部文件系统(本地或HDFS) state:TaskManager上的KV数据库(实际使用内存+磁盘)checkpoint:外部文件系统(本地或者HDFS)
容量限制 单个State maxStateSize 默认5M, maxStateSize 单TaskManager上State总量不超过它的内存,总大小不超过配置的文件系统容量 单TaskManager上State总量不超过它的内存+磁盘单key最大2G, 总大小不超过配置的文件系统容量
推荐使用的场景 本地测试;几乎无状态的作业,比如:ETL;JobManage不容易挂,或者挂掉影响不大的情况.不推荐在生产场景使用 常规使用状态的作业,例如:分钟级窗口聚合、join;需要开启HA的作业可以在生产场景使用 超大状态的作业,例如:天级窗口聚合;需要开启HA的作业,对状态读写性能要求不高的作业可以在生产场景使用

2.3.checkPoint vs savePoint

checkPoint

  • 应用定时触发,用于保存状态,会过期
  • 内部应用失败重启的时候使用

savePoint

  • 用户手动执行,是指向Checkpoint的指针,不会过期
  • 在升级的情况下使用

注意:为了能够在作业的不同版本之间以及 Flink 的不同版本之间顺利升级,强烈推荐程序员通过 uid(String) 方法手动的给算子赋予 ID,这些 ID 将用于确定每一个算子的状态范围。如果不手动给各算子指定 ID,则会由 Flink 自动给每个算子生成一个 ID。只要这些 ID 没有改变就能从保存点(savepoint)将程序恢复回来。而这些自动生成的 ID 依赖于程序的结构,并且对代码的更改是很敏感的。因此,强烈建议用户手动的设置 ID。

2.4.flink重启策略

  • Flink支持不同的重启策略,以在故障发生时控制作业如何重启
  • 集群在启动时会伴随一个默认的重启策略,在没有定义具体重启策略时会使用该默认策略。如果在工作提交时指定了一个重启策略,该策略会覆盖集群的默认策略
  • 默认的重启策略可以通过 Flink 的配置文件 flink-conf.yaml 指定。配置参数 restart-strategy定义了哪个策略被使用。
  • 常用的重启策略
       1.固定间隔 (Fixed delay)
       2.失败率 (Failure rate)
       3.无重启 (No restart)

1.如果没有启用 checkpointing,则使用无重启 (no restart) 策略。
2.如果启用了 checkpointing,但没有配置重启策略,则使用固定间隔 (fixed-delay) 策略,其中 Integer.MAX_VALUE 参数是尝试重启次数.
3.重启策略可以在flink-conf.yaml中配置,表示全局的配置。也可以在应用代码中动态指定,会覆盖全局配置.

3.Window

CountWindow TimeWindow
滚动窗口、滑动窗口、会话session窗口
Flink四大核心组件:State、Checkpoint、Window、Time_第1张图片

3.1window的类型

3.1.1.countWindow使用

Flink四大核心组件:State、Checkpoint、Window、Time_第2张图片

3.2.timeWindow使用

Flink四大核心组件:State、Checkpoint、Window、Time_第3张图片

3.3.自定义window

Flink四大核心组件:State、Checkpoint、Window、Time_第4张图片

3.2.window聚合

3.2.1.增量聚合

窗口中每进入一条数据,就进行一次计算
reduce(reduceFunction)
aggregate(aggregateFunction)
sum(),min(),max()
Flink四大核心组件:State、Checkpoint、Window、Time_第5张图片
reduce:
Flink四大核心组件:State、Checkpoint、Window、Time_第6张图片
aggregate
Flink四大核心组件:State、Checkpoint、Window、Time_第7张图片

3.2.2.全量聚合

等属于窗口的数据到齐,才开始进行聚合计算【可以实现对窗口内的数据进行排序等需求】
apply(windowFunction)
process(processWindowFunction)
processWindowFunction比windowFunction提供了更多的上下文信息。
Flink四大核心组件:State、Checkpoint、Window、Time_第8张图片
apply:
Flink四大核心组件:State、Checkpoint、Window、Time_第9张图片
process:
Flink四大核心组件:State、Checkpoint、Window、Time_第10张图片
Flink四大核心组件:State、Checkpoint、Window、Time_第11张图片

4.Time

4.1、Flink如何处理乱序?

watermark+window机制
window中可以对input进行按照Event Time排序,使得完全按照Event Time发生的顺序去处理数据,以达到处理乱序数据的目的。
如果有多个watermark机制,以最后一个为准

4.2、Flink何时触发window?

1、watermark时间 > Event Time(对于late element太多的数据而言)
或者
1、watermark时间 >= window_end_time(对于out-of-order以及正常的数据而言)
2、在[window_start_time,window_end_time)中有数据存在
输入的数据中,根据自身的 Event Time,将数据划分到不同的 window 中,如果 window 中 有数据,则当 watermark 时间>=Event Time 时,就符合了 window 触发的条件了,最终决定 window 触发,还是由数据本身的 Event Time 所属的 window 中的 window_end_time 决定。

4.3、Flink应该如何处理乱序数据,处理最大乱序时间?

window+waterMark
这个要结合自己的业务以及数据情况去设置。如果maxOutOfOrderness(最大允许乱序时间 )设置的太小,而自身数据发送时由于网络等原因导致乱序或者late太多,那么最终的结果就是会有很多单条的数据在window中被触发,数据的正确性影响太大
对于严重乱序的数据,需要严格统计数据最大延迟时间,才能保证计算的数据准确,延时设置太小会影响数据准确性,延时设置太大不仅影响数据的实时性,更加会加重Flink作业的负担,不是对eventTime要求特别严格的数据,尽量不要采用eventTime方式来处理,会有丢数据的风险。

4.4、多并行度流的watermarks

注意:多并行度的情况下,watermark对齐会取所有channel最小的watermark
Flink四大核心组件:State、Checkpoint、Window、Time_第12张图片

4.5、watermarks的生成方式

通常,在接收到source的数据后,应该立刻生成watermark;但是,也可以在source后,应用简单的map或者filter操作后,再生成watermark。
注意:如果指定多次watermark,后面指定的会覆盖前面的值。
生成方式
•With Periodic Watermarks
•周期性的触发watermark的生成和发送,默认是100ms
•每隔N秒自动向流里注入一个WATERMARK 时间间隔由ExecutionConfig.setAutoWatermarkInterval 决定. 每次调用getCurrentWatermark 方法, 如果得到的WATERMARK 不为空并且比之前的大就注入流中
•可以定义一个最大允许乱序的时间,这种比较常用
•实现AssignerWithPeriodicWatermarks接口

class MyWatermarksService extends AssignerWithPeriodicWatermarks[(String, Int, String)] {
  var currentMaxTimestamp = 0L
  val maxOutOfOrderness = 10000L //最大允许的乱序时间是10s
  var a: Watermark = null
  val format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")

  override def getCurrentWatermark: Watermark = {
    a = new Watermark(currentMaxTimestamp - maxOutOfOrderness)
    a
  }

  override def extractTimestamp(str: (String, Int, String), l: Long): Long = {
    val timestamp = str._3.toLong
    currentMaxTimestamp = Math.max(timestamp, currentMaxTimestamp)
    timestamp
  }
}

With Punctuated Watermarks
•基于某些事件触发watermark的生成和发送
•基于事件向流里注入一个WATERMARK,每一个元素都有机会判断是否生成一个WATERMARK. 如果得到的WATERMARK 不为空并且比之前的大就注入流中
•实现AssignerWithPunctuatedWatermarks接口

4.6、Flink 对late element(延迟数据)的处理方式

1、丢弃(默认的方式)
2、allowedLateness 指定允许数据延迟的时间
第二次(或多次)触发的条件是 watermark < window_end_time + allowedLateness 时间内, 这个窗口有 late 数据到达时。

3、sideOutputLateData 收集迟到的数据

你可能感兴趣的:(Flink)