一、背景

Flink的容错机制,就是checkpoint;把状态保存起来,用于容错;否则,状态就失去了存在的意义。

二、checkpoint详解

1)概念

①一种连续周期性绘制数据流状态的机制。这种机制确保即使程序出现故障,也可以顺利恢复到故障之前的状态,确保exactly once语义的保证。

   注意:这种保证,只能在flink内部系统做保证,对于外部的source和sink,需要外部主键一同保证

②全局快照,持久化保存所有的task和operator的state

③可以通过配置,使用at least once语义保证

④checkpoint是通过分布式snapshot实现的

2)特点

①可异步:在程序正常运行的过程中,异步完成,不会干扰程序的正常运行

②全量/增量:一般是全量;也可设置增量

③barrier机制

④失败后回滚最近一次成功的checkpoint

3)前提条件

①在一定时间内可回溯的DataSource(故障是可以恢复),常见的有:

  1. 可持久化的队列:Kafka,RabbitMQ等
  2. 文件系统:HDFS,S3,GFS,NFS,Ceph

②可持久化存储state的存储系统,通常使用分布式文件系统

  1. 一般使用HDFS,S3,GFS,NFS,Ceph等

三、过程

1)checkpoint

将各个state保存起来到指定的存储系统中(checkpoint)

flink cdc块读取算法 flink cdc checkpoint_flink

2)restore

恢复所有状态

flink cdc块读取算法 flink cdc checkpoint_flink cdc块读取算法_02

四、使用

1)第一步:启用checkpoint

StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

    // checkpoint默认是禁用的;启用checkpoint
    // 每1000毫秒做一次checkpoint
    env.enableCheckpointing(1000);

    // 设置checkpoint的模式为 exactly-once(默认配置)
    env.getCheckpointConfig().setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE);

    // 设置每两个checkpoint之间最小时间间隔
    env.getCheckpointConfig().setMinPauseBetweenCheckpoints(500);

    // 设置checkpoint超时时间
    env.getCheckpointConfig().setCheckpointTimeout(60000);

    // 设置同一时间checkpoint的最大并行数
    env.getCheckpointConfig().setMaxConcurrentCheckpoints(1);

    // 任务流取消和故障时会保留Checkpoint数据,以便根据实际需要恢复到指定的Checkpoint
    env.getCheckpointConfig().enableExternalizedCheckpoints(CheckpointConfig.ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION);

①checkpoint的模式 CheckpointMode

  1. CheckpointMode.EXACTLY_ONCE
  2. CheckpointMode.AT_LEAST_ONCE
  3. 一般选择EXACTLY_ONCE,除非场景要求极低的延迟(几毫秒)
  4. 如果需要保证整个流程的EXACTLY_ONCE,source和sink也需要保证EXACTLY_ONCE 

②checkpoint的保留策略 ExternalizedCheckpointCleanup

  1. 默认情况下,检测点不被保留,仅用于从故障中恢复作业,可以启用外部持久化检查点,同时制定保留策略
  2. ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION,在作业被取消时保留检查点;这种情况下,必须在作业取消之后,手动清理检查点状态。
  3. ExternalizedCheckpointCleanup.DELETE_ON_CANCELLATION,在作业被取消时清理检查点;这种情况下,检查点状态只有在作业失败重启时可用,手动取消作业,检查点被清理不可用。

③checkpoint的超时时间

  1. env.getCheckpointConfig().setCheckpointTimeout(6000)
  2. 超过时间没有完成,则会被终止

④checkpoint的最小间隔

  1. env.getCheckpointConfig().setMinPauseBetweenCheckpoints(500)
  2. 用于指定上一个checkpoint完成之后至少等多久才可以发出另一个checkpoint
  3. 当指定这个参数时,maxConcurrentCheckpoints的值为1
    备注:个人觉得,设置周期并设置最小间隔 最合理

⑤checkpoint的最多并行度

  1. env.getCheckpointConfig().setMaxConcurrentCheckpoints(1)
  2. 用于指定同时运行的checkpoint可以有多少个

⑥checkpoint的异常处理

  1. env.getCheckpointConfig().setFailOnCheckpointingErrors(true)
  2. 用于指定在checkpointing发生异常时,是否应该使该task失败重试
  3. 默认为true
  4. 如果设置为false,在checkpoint失败后,任务仍然会继续运行

2)第二步:选择合适的state Backend

①快照保存位置

  1. State Backend决定:MemoryStateBackend(默认)、FsStateBackend、RocksDBStateBackend
  2. 默认state保存在taskmanager的内存中,checkpoint存储在JobManager的内存中(MemoryStateBackend)

②保存的内容

Checkpoint机制会持久化所有状态的一次性快照,这些状态包括:

非用户定义的状态:timers、非用户定义的stateful operators(connectors,windows)

用户定义的状态:用户自定义的stateful operator所使用的Keyed State 和 Operator State

3)第三步:配置重启策略

①重启策略说明

Flink支持不同的重启策略,这些策略控制 在出现故障时如何重新启动job
 

Restart Strategy

配置项

默认值

说明

固定延迟(Fixed delay)

restart-strategy: fixed-delay

 

如果超过最大尝试次数,作业最终会失败,在连续两次重启尝试之间等待固定时间

restart-strategy: fixed-delay.attempts: 3

1(启动Checkpoint和延迟策略使用fixed-delay,但是没配置fixed-delay.attempts)或者

Integer.MAX_VALUE(启用checkpoint但未指定重启策略时)

restart-strategy: fixed-delay.delay: 10s

akka.ask.timeout (启动checkpoint和延迟策略使用fixed-delay,但是没配置fixed-delay.delay)或者

10s(启动checkpoint,但是没指定重启策略)

失败率(Failure rate)

restart-strategy: failure-rate

 

在失败后重新启动作业,但是当超过故障率(每个时间间隔的故障)时,作业最终会失败,在连续两次重启尝试之间等待固定的时间

restart-strategy: failure-rate.max-failures-per-interval: 3

1

restart-stragery: failure-rate.failure-rate-interval: 5 min

1 minute

restart-stragery: failure-rate.delay: 10s

akka.ask.timeout

无启动(No restart)

restart-strategy: none

 

如果没有启动checkpointing,则使用无重启(no restart)策略

注意:代码配置会覆盖配置文件配置,即代码配置优先于配置文件配置。

②tips

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

4)三个保存策略详解

①MemoryStateBackend

  1. MemoryStateBackend在Java堆上维护状态,Key/value状态和窗口运算符使用哈希表存储值和计时器等
  2. Checkpoint时,MemoryStateBackend对State做一次快照,并在向JobManager发送checkpoint确认完成的消息中带上此快照数据,然后快照就会存储在JobManager的堆内存中
  3. MemoryStateBackend可以使用异步方式进行快照(默认开启),推荐使用异步的方式,避免阻塞。如果极特殊情况不希望异步,可以在构造的时候传入false(也可以通过全局配置文件指定),如下
  4. 限制:
    单个state的大小限制为5MB,可以在MemoryStateBackend的构造函数中增加
    不论如何配置,state的大小都无法大于 akka.framesize(JobManager 和 TaskManager之间发送的最大消息的大小默认是10MB)
    JobManager必须有足够的内存大小
  5. 使用场景:
    本地开发和测试
    小状态job,如只使用Map、FlatMap、Filter... 或 Kafka Consumer

②FsStateBackend

  1. 需要配置一个文件系统的URL,比如"hdfs://namenode:40010/flink/checkpoint"或者"file:///data/flink/checkpoints"
  2. FsStateBackend在TaskManager的内存中持有正在处理的数据。Checkpoint时将state snapshot写入文件系统目录下的文件中。文件的路径等元数据会传递给JobManager,存在其内存中(或者在HA模式下,存储在元数据checkpoint中)
  3. FsStateBackend可以使用异步的方式进行快照(默认开启),推荐使用异步的方式避免阻塞。如果极特殊情况下不希望异步,可以在构造的时候传入false(也可以通过全局配置文件制定),如下
  4. 使用场景:
    大状态,长窗口,大键/值状态的job
    所有高可用性的情况

③RocksDBStateBackend

  1. Flink内部维护,不需要用户维护,对于用户透明
  2. RocksDBStateBackend需要配置一个文件系统的URL,如"hdfs://namenode:40010/flink/checkpoint"或者"file:///data/flink/checkpoints"。
  3. RocksDBStateBackend将运行中的数据保存在RocksDB数据库中,(默认情况下)存储在TaskManager数据目录中。在Checkpoint时,整个RocksDB数据库将被checkpointed到配置的文件系统中和目录中。文件的路径等元数据会传输给JobManager,存在其内存中(或者在HA模式下,存储在元数据checkpoint中)。
  4. RocksDBStateBackend总是执行异步快照
  5. 限制:
    RocksDB JNI API是基于 byte[],因此 key 和 value 最大支持大小为2^31个字节(2GB)。RocksDB自身在支持较大value时候有问题(merge operations in RocksDB(e.g. ListState))
  6. 适用场景
    超大状态、超长窗口、大键/值状态的job
    所有高可用性的情况
  7. 与前两种状态后端对比
    目前只有RocksDBStateBackend支持增量checkpoint(默认全量)
    状态保存在数据库中,即使用RocksDB可以保存的状态量仅受可用磁盘空间量的限制,相比其他状态后端可保存更大的状态,但开销更大(读/写需要反序列化 / 序列化去检索 / 存储状态),吞吐受到限制

④StateBackend总结 

State Backend

in-flight

checkpoint

异步

增量checkpoint

吞吐

适用场景

MemoryStateBackend(默认)

TM Memory

JM Memory

默认异步

不支持


调试、无状态、小状态或对数据丢失或者重复无要求的job

FsStateBackend

TM Memory

FS / HDFS

默认异步

不支持


大状态、长窗口、大键 / 值状态的job

RocksDBStateBackend

RocksDB on TM

FS / HDFS

总是异步

支持


越大状态、超长窗口、大型KV结构

⑤StateBackend配置

  1. 全局配置(配置文件conf/flink-conf.yaml)
# The backend that will be used to store operator state checkpoints

state.backend: filesystem

# Direcroty for storing checkpoints

state.checkpoints.dir: hdfs://namenode:40010/flink/checkpoints
  1. 每个job单独配置State Backend(可覆盖全局配置)
  2. Checkpointing的相关配置(conf/flink-conf.yaml)

配置项

默认值

说明

(*)state.backend

(none)

  1. 用于指定checkpoint state存储的backend,默认为none
  2. 目前支持的backends是‘jobmanager’,‘filesystem’,‘rocksdb’
  3. 也可以使用它们的工厂类的全限定名:例如org.apache.flink.runtime.state.filesystem.FsStateBackendFactory
  4. 如果没有指定,默认使用jobmanager,即MemoryStateBackend

(*)state.backend.async

true

用于指定backend是否使用异步,有些不支持async或者只支持async的state backend可能会忽略这个参数

state.backend.fs.memory-threshold

1024

用于指定存储state的files大小阈值,如果小于该值,则会存储在root checkpoint metadata file

state.backend.incremental

false

用于指定是否采用增量checkpoint,有些不支持增量checkpoint的backend会忽略该配置;目前只有rockddb支持

state,backend.local-recovery

false

 

(*)state.checkpoints.dir

(none)

  1. 用于指定checkpoint的data files 和 meta data存储的目录,该目录必须对所有参与的TaskManager 和 JobManager 可见(有读写权限)
  2. 例如:hdfs://namenode-host:port/flink-checkpoints

(*)state.checkpoints.num-retained

1

用于指定保留的已完成的checkpoints最大个数

(*)state.savepoints.dir

(none)

  1. 用于指定savepoints的默认目录
  2. 例如:hdfs://namenode-host:port/flink-checkpoints

taskmanager.state.local.root-dirs

(none)

 

⑥使用RocksDBStateBackend

  1. 特有配置(conf/flink-conf/yaml)

配置项

默认值

说明

state.backend.rocksdb.localdir

(none)

 

state.backend.rocksdb.timerservice.factory

"HEAP"

指定timer service状态存储在哪里,HEAP / ROCKSDB

  1. 代码配置


    备注:以上配置,需要在pom中添加如下依赖