主要内容:

  • 介绍有状态计算及状态后端

1 有状态计算

有状态计算是Flink非常重要的特性之一。什么是状态?一般来说,状态是由一个task维护,并用于计算某个结果的所有数据,都属于这个任务的状态。也可以理解为一个本地变量,可以被task的业务逻辑访问。下图展示了一个task与它的state的常规交互过程:task在处理数据时,会先访问state,并根据输入信息和state信息更新state。

Flink会处理所有关于state一致性、故障处理、高效存储并访问等问题,开发者仅需关注在他们的应用逻辑即可。在Flink中,状态始终与特定算子相关联。为了让Flink的runtime可以意识到一个operator的state,operator需要注册它的state。

Flink中包含两种基础的状态:

  • Keyed State:键控状态,表示和key相关的一种state,基于KeyedStream上的状态。键控状态数据结构:
    • value state:将state表示为单个值
    • list state:以list表示state
    • map state:以map,key-value对表示state
  • Operator State:算子状态,作用范围限定为算子任务,一个任务一个状态。同一任务共享state。算子状态数据结构:
    • list state:列表状态,以list结构表示state
    • union list state:联合列表状态,同样以list表示state,与list state不同在于:发生故障恢复的方式,或从检查点开始的方式
    • broadcast state:广播状态,当一个operator的每个task的state都是相同时使用

2 状态后端(State Backends)

在有状态的流处理中,当开发人员启用了 Flink 中的 checkpoint 机制,那么状态将会持久化以防止数据的丢失并确保发生故障时能够完全恢复。选择何种状态后端,将决定状态持久化的方式和位置。

Flink 提供了三种可用的状态后端:MemoryStateBackendFsStateBackend,和RocksDBStateBackend

2.1 状态后端类型

  • MemoryStateBackend:基于TaskManager的JVM堆内存,支持异步快照以避免阻塞数据流的处理。使用时需要注意:

    • 默认情况下,每个状态大小限制为5M。
    /** The default maximal size that the snapshotted memory state may have (5 MiBytes). */
    public static final int DEFAULT_MAX_STATE_SIZE = 5 * 1024 * 1024;
    
    • 特点:快速、低延迟、但不稳定(内存溢出、丢失)、适用于测试环境
  • FsStateBackend:基于文件系统存储,可以是本地文件系统,也可以是HDFS分布式文件系统

    path = "file:///data/flink/checkpoints"
    path = "hdfs://nameserver/flink/checkpoints"
    

    FsStateBackend的第二个参数表示是否以同步的方式进行状态数据的记录,可设置为false。

    • 特点:适用于处理大状态、长窗口,或大键值状态的有状态处理任务;非常适合用于高可用方案。
  • RocksDBStateBackend:将所有数据序列化后,存入到本地的RocksDB中。RocksDB是一种嵌入式本地数据库。RocksDB 默认也是配置成异步快照的模式。序列化过程可能会影响程序吞吐量。

    • 特点:适用于处理大状态、长窗口,或大键值状态的有状态处理任务;非常适合用于高可用方案;是目前唯一支持增量checkpoint的后端,非常适合于超大状态的场景。

不同状态后端满足不同场景的需求,在开始开发应用程序之前应该仔细考虑和规划后选择。这可确保选择了正确的状态后端以最好地满足应用程序和业务需求。