Flink从无到有(5)

328 阅读3分钟

这是我参与更文挑战的第6天,活动详情查看: 更文挑战

状态后端 State Backends

  • 每传入一条数据,有状态的算子任务都会读取和更新状态。
  • 由于有效的状态访问对于处理数据的低延迟至关重要,因此每个并行任务都会在本地维护其状态,以确保快速的状态访问。
  • 状态的存储、访问以及维护,由一个可插入的组件决定,这个组件就叫做状态后端( state backend)
  • 状态后端主要负责两件事:本地状态管理,以及将检查点(checkPoint)状态写入远程存储

在Flink中提供了StateBackend来存储和管理状态数据 Flink一共实现了三种类型的状态管理器:

  • MemoryStateBackend

    • 内存级的状态后端,会将键控状态作为内存中的对象进行管理,将它们存储在TaskManager的JVM堆上,而将checkpoint存储在JobManager的内存中
    • 特点:快速、低延迟,但不稳定**(内存的限制:内存泄漏、内存溢出等)**
    • 聚合类算子的状态会**同步到JobManager内存中,因此对于聚合类算子比较多的应用会对JobManager的内存造成一定的压力**,进而影响集群
    public class StateBackendDemo {
        public static void main(String[] args) {
            StreamExecutionEnvironment env = StreamExecutionEnvironment
                                                    .getExecutionEnvironment();
            /**
             * 设置100M大小的MemoryState
             */
            env.setStateBackend(new MemoryStateBackend(100 * 1024 * 1024));
        }
    }
    
  • FsStateBackend**(默认)**

    • 将checkpoint存到远程的持久化文件系统(FileSystem)上(可以是**本地文件**,也可以是**分布式hdfs文件系统**),而对于本地状态,跟MemoryStateBackend一样,也会存在TaskManager的JVM堆上
    • 同时拥有内存级的本地访问速度,和更好的容错保证
    public class FsStateBackendDemo {
        public static void main(String[] args) {
            StreamExecutionEnvironment env = StreamExecutionEnvironment
                    .getExecutionEnvironment();
             /**
             * 第二个参数代表是否异步保存状态数据到HDFS,异步方式能够尽可能避免checkpoint的过程中影响流
             * 式计算任务。
             * FsStateBackend更适合任务量比较大的应用,例如:包含了时间范围非常长的窗口计算,或者状态比
             * 较大的场景
             */
            env.setStateBackend(
                    new FsStateBackend(
                            "hdfs://192.168.1.1/checkpoint",
                            true)
                    );
        }
    }
    
  • RocksDBStateBackend

    • 将所有状态序列化后,存入本地的RocksDB中存储
    <!--需要添加的依赖-->
    				<dependency>
                <groupId>org.apache.flink</groupId>
                <artifactId>flink-statebackend-rocksdb_2.11</artifactId>
                <version>${flink.version}</version>
            </dependency>
    
    public class RocksDBStateBackendDemo {
        public static void main(String[] args) throws IOException {
            StreamExecutionEnvironment env = StreamExecutionEnvironment
                    .getExecutionEnvironment();
            env.setStateBackend(new RocksDBStateBackend("hdfs://"));
        }
    }
    
    

    RocksDBStateBackend采用异步的方式进行状态数据的Snapshot,任务中的状态数据首先被写入本地RockDB中,这样在RockDB仅会存储正在进行计算的热数据,而需要进行CheckPoint的时候,会把本地的数据直接复制到远端的FileSystem中。

    与FsStateBackend相比,RocksDBStateBackend在性能上要比FsStateBackend高一些,主要是因为借助于RocksDB在本地存储了最新热数据,然后通过异步的方式再同步到文件系统中,但RocksDBStateBackend和MemoryStateBackend相比性能就会较弱一些。RocksDB克服了State受内存限制的缺点,同时又能够持久化到远端文件系统中,推荐在生产中使用

集群级配置StateBackend

全局配置需要需改集群中的配置文件,修改flink-conf.yaml

jobmanager.execution.failover-strategy: region

#上面这个region指,多个并行度的任务要是有个挂掉了,只重启那个任务所属的region(可能含有多个子任务),而不需要重启整个Flink程序

配置FsStateBackend

state.backend: filesystem 
state.checkpoints.dir: hdfs://namenode-host:port/flink-checkpoints

配置MemoryStateBackend

state.backend: jobmanager

配置RocksDBStateBackend

state.backend.rocksdb.checkpoint.transfer.thread.num: 1  #同时操作RocksDB的线程数
state.backend.rocksdb.localdir: 本地path    # RocksDB存储状态数据的本地文件路径