首先的话,先来介绍一下,Flink的状态

flink任务执行可视化 flink任务状态_数据

1、每一个算子在启动时,都会先Flink集群,注册自己的状态

2、这个状态,最初放在内存,会被持久化到磁盘,或者数据库

3、每次我接受到数据,需要计算的时候,会在拿到数据之后,先去获取存储在内存中的状态,(比如我在求和,我就会先把状态里面的结果拿出来,然后跟现在的累加)

4、拿到状态,进行运算,算完,去更新状态,然后数据继续往下走

补充:
- 状态不能跨任务访问,状态跟特定的算子关联

- 算子需要预先注册其状态  注册个Flink
- 一个并行度里面都有一个分区
状态

1、某个算子或者key当前的状态,因为处理的是实时数据,我们需要对这个状态进行操作或者管理

2、 分类 算子的分类

  • Operator State 每个并行度存储一个状态
  • 状态对同一个子任务而言,是共享的,也只能被同一个子任务所访问
  • 只要在同一个分区,不管key是什么 访问的都是同一个状态
  • Keyed State 根据输入数据流中定义的键(key)来维护和访问
  • 首先得有keyby操作
  • 根据key,来保存状态(可能一个分区(task)里面存储不止一个key(有几个key 就有几个keyState))

flink任务执行可视化 flink任务状态_大数据_02


3、两种状态的区别

flink任务执行可视化 flink任务状态_java_03


4、分类 算子的管理

  • managed state Flink 管理 调用API即可
  • raw state 自己管理

容错机制

flink任务执行可视化 flink任务状态_数据_04

简介
  • Apache Flink提供了一种容错机制,可以持续恢复数据流应用程序的状态。该机制确保即使出现故障,经过恢复,程序的状态也会回到以前的状态。
  • Flink支持at least once语义和exactly once语义
  • Flink通过定期地做checkpoint来实现容错和恢复,容错机制不断地生成数据流的快照。对于小状态的流应用程序,这些快照非常轻量级并且可以经常生成快照,而不会对性能产生太大的影响。流应用程序的状态存储在一个可配置的地方(例如主节点或HDFS)。
  • 如果出现程序故障(由于机器、网络或软件故障),Flink将停止分布式流数据流。然后系统重新启动operator,并将其设置为最近一批的检查点。
  • 注意:
  • 默认情况下,禁用checkpoint(检查点)
  • 要使得容错机制正常运行,数据流source需要能够将流倒回到指定的之前的点。比如Apache Kafka有这种方法,flink与Kafka的connector可以利用重置kafka topic的偏移量来达到数据重新读取的目的。
Barriers(栅栏)

这里说的 是并行的场景(也基本不会只有一个分区的)
Flink的分布式快照的核心元素是stream barriers。这些barriers被注入到数据流中,作为数据流的一部分和其他数据一同流动,barriers不会超过其他数据提前到达(乱序到达)。一个Barrier将数据流中的数据分割成两个数据集,即进入当前快照的数据和进入下一次快照的数据。每个Barrier带有一个ID,该ID为将处于该Barrier之前的数据归入快照的检查点的ID。Barrier不会打断数据流的流动,所以它是十分轻量级的。来自不同的快照的多个Barrier可以同一时间存在于同一个流中,也就是说,不同的快照可以并行同时发生。如下图所示:

flink任务执行可视化 flink任务状态_flink_05

  • Barrier是在source处被插入到数据流中的。快照n的barrier被插入的点(记为Sn),这个点就是在源数据流中快照n能覆盖到的数据的最近位置。如在Apache Kafaka中,这个位置就是上一个数据(record)在分区(partition)中的偏移量(offset)。这个位置Sn将会交给checkpoint 协调器(它位于Flink的JobManager中)。
  • 这些Barrier随数据流流动向下游,当一个中间Operator在其输入流接收到快照n的barrier时,它在其所有的输出流中都发送一个快照n的Barrier。当一个sinkoperator(流DAG的终点)从其输入流接收到n的Barrier,它将快照n通知给checkpoint coordinator(协调器)。在所有Sink都通知了一个快照后,这个快照就完成了。
  • 当快照n完成后,由于数据源中先于Sn的的数据已经通过了整个data flow topology,我们就可以确定不再需要这些数据了。
Checkpoints

默认情况下,flink禁用检查点。

1、这里要分两种情况,一种是只有一次,一种最少一次
2、只有一次:
	1)、当不同的数据源,流到Barriers时,会进入等待状态,等待其他并行的数据源全部来到,一起拍快照
	2)、此时后面在到来的是数据就说属于下一个checkpoint  所以会暂时进入缓冲区
	3)、算子之间,分区不改变的时候,谁先到了栅栏处(每一个并行度里面都会有栅栏),谁就拍照,拍完先把结果放到taskManager,然后需要持久化的时候走状态后端 快照的映射信息由jobManger通一管理
	4)、补充:这里的jobManager  会对你的快照进行管理,把他们收集到一起,方便恢复(其他只是把元数据记录在一起)
2、最少一次:
	1)、当不同分区的数据来临之后,各自拍快照,然后广播下去  就继续数据的传输,如果出现了错误,就需要从上一个数据源重新发送数据,这也就形成了最少一次
恢复Recovery
  • link恢复时的机制是十分直接的:在系统失效时,Flink选择最近的已完成的检查点k,系统接下来重部署整个数据流图,然后给每个Operator在检查点k时的相应状态。数据源则被设置为从数据流的Sk位置开始读取。例如,在Apache Kafka执行恢复时,系统会通知消费者从偏移Sk开始获取数据。
  • 这里的数据源,最好还是持续的数据源,比如消息队列(例如,Apache Kafka,RabbitMQ)或文件系统(例如,HDFS,S3,GFS,NFS,Ceph,…)。
State Backends -->后端状态 状态的存储地

Flink 在保存状态时,支持三种存储方式,如下:

MemoryStateBackend (基于内存存储)

  • 快速,低延迟,但不稳定
  • 状态存在taskManager内存里,checkpoint存在 jobManager内存里一般做测试用,实际生产环境不用

FsStateBackend (基于文件系统存储)

  • 本地状态存在taskManager内存里,checkpoint文件系统里
  • 实际生产会使用

RocksDBStateBackend (基于RocksDB数据库存储)

  • 实际生产会使用
  • 做序列化后,存在本地的RocksDB里面
  • 每次只记录发生变更的数据
  • 读写,访问速度会慢点

补充:如果没有配置其他任何内容,系统默认将使用MemoryStateBackend。

如有不同见解,欢迎交流!