flink DataStream API(四)状态和容错-checkpointing

checkpointing

Flink 中的每个函数和算子都可以是有状态的。有状态函数在单个元素/事件的处理过程中存储数据,使状态成为任何类型的更复杂操作的关键组成部分。

为了使状态能够容错,Flink需要对状态进行检checkpointcheckpoint允许Flink恢复流中的状态和位置,为应用程序提供与无故障执行相同的语义。

前提条件

Flink的checkpoint机制与流和状态的持久存储交互。一般而言,它要求:

  • 可以在一定时间内重放记录的持久(或持久)数据源。此类源的示例包括持久消息队列(例如,Apache Kafka、RabbitMQ、Amazon Kinesis、Google PubSub)或文件系统(例如HDFS、S3、GFS、NFS、Ceph等)。
  • 状态的持久存储,通常是分布式文件系统(例如 HDFS、S3、GFS、NFS、Ceph 等)

启用和配置checkpoint

默认情况下,checkpoint是禁用的。要启用checkpoint,请在 StreamExecutionEnvironment 上调用 enableCheckpointing(n),其中 n 是以毫秒为单位的checkpoint间隔。

checkpoint的其他参数包括:

  • checkpoint存储:您可以设置checkpoint快照持久化的位置。默认情况下,Flink 将使用 JobManager 的堆。对于生产部署,建议改用持久化到文件系统。详细信息请参考 checkpoint storage

  • Exactly-once与至少一次:您可以选择将模式传递给enableCheckpointing(n)方法,以便在两个保证级别之间进行选择。Exactly-once 对于大多数应用来说是可取的。 At-least-once 可能应用到某些超低延迟(持续几毫秒)的应用程序中。

  • checkpoint超时:当正在进行的checkpoint没有在超时时间完成,则正在进行的checkpoint会被终止。

  • checkpoint之间的最短时间checkpoint之间的最短时间。例如,如果将该值设置为5000,则下一个checkpoint将在前一个checkpoint完成后不超过5秒启动,无论checkpoint持续时间和checkpoint间隔是多少。请注意,这意味着checkpoint间隔永远不会小于此参数。

    通过定义“checkpoint之间的时间”而不是checkpoint间隔来配置应用程序通常更容易,因为“checkpoint之间的时间”不易受到checkpoint有时花费的时间可能比平均时间长这一事实的影响(例如,如果目标存储系统暂时变慢)。

    注意,这个值还意味着并发checkpoint的数量为1

  • 并发checkpoint的数量:默认情况下,当一个checkpoint仍在进行中时,系统不会触发另一个checkpoint。如果定义了checkpoint之间的最短时间,则无法使用此选项。

  • 外部checkpoint:您可以将定期checkpoint配置为持久化到外部。外部checkpoint将其元数据写入持久性存储,并且在作业失败时不会自动清除。这样,如果您的作业失败,您将有一个checkpoint可供恢复。关于外部化checkpoint的部署说明请参考deployment notes on externalized checkpoints

  • checkpoint失败使任务失败还是继续运行:这决定了如果在执行任务的checkpoint过程中发生错误,任务是否失败。默认请款下,checkpoint失败会导致任务失败。当它被禁用时,任务会继续运行而不会失败。

  • 优先选择用于恢复的checkpoint:此选项确定作业是否会回退到最新的checkpoint。即使最近有可用的保存点,这可能会减少恢复的时间。

  • 未对齐的checkpoint:您可以启用未对齐的checkpoint以大大减少背压下的checkpoint时间。仅适用于Exactly-once``checkpoint且并发checkpoint数为 1

StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

// start a checkpoint every 1000 ms
env.enableCheckpointing(1000);

// advanced options:

// set mode to exactly-once (this is the default)
env.getCheckpointConfig().setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE);

// make sure 500 ms of progress happen between checkpoints
env.getCheckpointConfig().setMinPauseBetweenCheckpoints(500);

// checkpoints have to complete within one minute, or are discarded
env.getCheckpointConfig().setCheckpointTimeout(60000);

// allow only one checkpoint to be in progress at the same time
env.getCheckpointConfig().setMaxConcurrentCheckpoints(1);

// enable externalized checkpoints which are retained 
// after job cancellation
env.getCheckpointConfig().enableExternalizedCheckpoints(
    ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION);

// enables the experimental unaligned checkpoints
env.getCheckpointConfig().enableUnalignedCheckpoints();

// sets the checkpoint storage where checkpoint snapshots will be written
env.getCheckpointConfig().setCheckpointStorage("hdfs://my/checkpoint/dir")

相关的配置选项

更多的参数和/或默认值可以通过conf/flink-conf.yaml。(见完整的 configuration):

配置项默认类型描述
state.backend.incrementalfalseBoolean是否指定状态后端创建增量检查点的选项。对于增量检查点,只存储与前一个检查点的差异,而不是完整的检查点状态。一旦启用,web UI中显示的状态大小或从rest API中获取的状态大小仅代表增量检查点大小,而不是完整的检查点大小。一些状态后端可能不支持增量检查点请忽略此选项。
state.backend.local-recoveryfalseBoolean这个选项为状态后端配置本地恢复。默认情况下,本地恢复是停用的。本地恢复目前仅涵盖键控状态后端。目前,MemoryStateBackend 和 HashMapStateBackend 不支持本地恢复,请忽略该选项。
state.checkpoint-storage(none)String用于存储检点的实现。这个实现可以通过指定快捷名称或者CheckpointStorageFactory的类名指定实现。如果指定了工厂,则通过其无参构造函数对其进行实例化,并调用其 CheckpointStorageFactory#createFromConfig(ReadableConfig, ClassLoader) 方法。可识别的快捷方式名称为“jobmanager”和“filesystem”。
state.checkpoints.dir(none)StringFlink 支持的文件系统中用于存储检查点的数据文件和元数据的默认目录。存储路径必须可以让所有参与的进程或者节点都能访问的到(例如:所有taskmanagerjobmanager)。
state.savepoints.dir(none)String保存点的默认目录。由将保存点写入文件系统的状态后端使用(HashMapStateBackend、EmbeddedRocksDBStateBackend)。
state.checkpoints.num-retained1Integer保留以完成的检查点的最大数量。
state.storage.fs.memory-threshold20 kbMemorySize状态数据文件的最小大小。所有比它小的状态块都存储在根检查点元数据文件中。此配置的最大内存阈值是1MB。
state.storage.fs.write-buffer-size4096Integer对于写入checkpoint流到文件系统中的写缓冲区的默认大小。实际写入缓冲区大小是该选项和选项“state.storage.fs.memory-threshold”中的最大值决定的。
taskmanager.state.local.root-dirs(none)String定义用于存储本地恢复的基于文件的状态的根目录配置参数。本地恢复目前只涵盖键控状态后端。目前,MemoryStateBackend不支持本地恢复,忽略此选项

选择检查点存储

Flink的检查点机制会将所有计时器和有状态算子(包括连接器、窗口和任何用户定义的状态)状态存储到一致快照中。存储检查点的位置(例如,JobManager内存、文件系统、数据库)取决于检查点存储的配置。

默认情况下,检查点存储在JobManager的内存中。为了将大的状态正确的持久化,flink支持各种各样的方法将检查点存储到其他地方。检查点存储的选择可以通过 StreamExecutionEnvironment.getCheckpointConfig().setCheckpointStorage(...) 进行配置。强烈建议将检查点存储在用于生产部署的高可用文件系统中。

迭代作业中的状态检查点

Flink 目前只为没有迭代的作业提供处理保障。在迭代作业上启用检查点会导致异常。为了在迭代程序上强制执行检查点,用户需要在启用检查点时设置一个特殊标志:env.enableCheckpointing(interval, CheckpointingMode.EXACTLY_ONCE, force = true)

执行流程

  1. 第一步:Checkpoint Coordinator向所有source节点trigger Checkpoint;
  2. 第二步:source节点向下游广播barrier,这个barrier就是实现Chandy-Lamport分布式快照算法的核心,下游的task只有收到所有input的barrier才会执行相应的Checkpoint。
  3. 第三步:当task完成state备份后,会将备份数据的地址(state handle)通知给Checkpoint coordinator。
  4. 第四步:下游的sink节点收集齐上游两个input的barrier之后,会执行本地快照,这里特地展示了RocksDB incremental Checkpoint的流程,首先RocksDB会全量刷数据到磁盘上,然后Flink框架会从中选择没有上传的文件进行持久化备份。
  5. 同样的:sink节点在完成自己的Checkpoint之后,会将state handle返回通知Coordinator。
  6. 最后:当Checkpoint coordinator收集齐所有task的state handle,就认为这一次的Checkpoint全局完成了,向持久化存储中再备份一个Checkpoint meta文件。

Barrier对齐

假设算子有两个上游输入

  1. 算子收到通道 1 的Barrier,没收到通道 2 的 Barrier ,算子会继续接收通道 1 的数据,但不处理,直接保存的输入缓存中,等待通道 2 的 Barrier
  2. 通道 2 的 Barrier 到达后,算子开始对其 State 进行异步快照,并将 Barrier 向下游传播,不用等待快照完成
  3. 算子异步快照时,算子首先处理缓存中的数据,在从通道中接受数据

EXACTLY_ONCE语义

为了实现EXACTLY ONCE语义,Flink通过一个input buffer将在对齐阶段收到的数据缓存起来,等对齐完成之后再进行处理。而对于AT LEAST ONCE 语义,无需缓存收集到的数据,会对后续直接处理,所以导致restore时,数据可能会被多次处理。

  • 一旦Operator从输入流接收到CheckPoint barrier n,它就不能处理来自该流的任何数据记录,直到它从其他所有输入接收到barrier n为止。否则,它会混合属于快照n的记录和属于快照n + 1的记录;

  • 接收到barrier n的流暂时被搁置。从这些流接收的记录不会被处理,而是放入输入缓冲区。

  • 虽然数字流对应的barrier已经到达了,但是barrier之后的1、2、3这些数据只能放到buffer中,等待字母流的barrier到达;

  • 一旦最后所有输入流都接收到barrier n,Operator就会把缓冲区中的数据出去,然后把CheckPoint barrier n接着往下游发送。

需要特别注意的是,Flink的Checkpoint机制只能保证Flink的计算过程可以做到EXACTLY ONCE,端到端的EXACTLY ONCE需要source和sink支持。

Savepoint与Checkpoint

  1. 首先最容易注意到的是 Savepoint 是一种特殊的 Checkpoint,实际上它们的存储格式也是一致的,它们主要的不同在于定位。Checkpoint 机制的目标在于保证 Flink 作业意外崩溃重启不影响 exactly once 准确性,通常是配合作业重启策略使用的。而 Savepoint 的目的在于在 Flink 作业维护(比如更新作业代码)时将作业状态写到外部系统,以便维护结束后重新提交作业可以到恢复原本的状态。换句话讲,Checkpoint 是为 Flink runtime 准备的,Savepoint 是为 Flink 用户准备的。因此 Checkpoint 是由 Flink runtime 定时触发并根据运行配置自动清理的,一般不需要用户介入,而 Savepoint 的触发和清理都由用户掌控。
  2. 其次,由于 Checkpoint 的频率远远大于 Savepoint,Flink 对 Checkpoint 格式进行了针对不同 StateBackend 的优化,因此它在底层储存效率更高,而代价是耦合性更强,比如不保证 rescaling (即改变作业并行度)的特性和跨版本兼容。这里说”不保证”而不是”不支持”,原因是实际上 RocksDB 的 Checkpoint 是支持 rescaling 的,”不保证”更多是从系统设计出发而言。跨版本兼容性也同理。
  3. 最后,Savepoint 的定义有提及它是 non-incremental 的,这是相对于 incremental Checkpoint 来说。因为 Checkpoint 是秒级频繁触发的,两个连续 Checkpoint 通常高度相似,因此对于 State 特别大的作业来说,每次 Checkpoint 只增量地补充 diff 可以大大地节约成本,这就是 incremental Checkpoint 的由来。而 Savepoint 并不会连续地触发,而且比起效率,Savepoint 更关注的是可移植性和版本兼容性,所以不支持 incremental 也是理所当然。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值