Flink个人学习整理-状态一致性篇(九)
状态后端
有状态的算子任务都会读取和更新状态,状态的存储、访问以及维护,由一个可插入的组件决定,这个组件就叫做状态后端(state backend)。
状态后端的作用
1、本地的状态管理
2、将检查点(checkpoint)状态写入远程存储
状态后端分类
1、MemoryStateBackend 内存级别状态后端
env.setStateBackend(new MemoryStateBackend());
本地状态存储在JobManager的内存中, checkpoint 存储在JobManager的内存中。
2、FsStateBackend 文件级别状态后端
env.setStateBackend(new FsStateBackend("hdfs://111.111.1.111:8020/flink/ck/fs"));
本地状态在JobManager内存, Checkpoint存储在文件系统中
3、RocksDBStateBackend RocksDB状态后端
env.setStateBackend(new RocksDBStateBackend("hdfs://111.111.1.111:8020/flink/ck/rocksdb"));
本地状态存储在TaskManager的RocksDB数据库中(实际是内存+磁盘) 2. Checkpoint在外部文件系统中.
状态后端的配置
1、全局配置状态后端
在flink-conf.yaml文件中设置默认的全局后端
2、在代码内配置
public class Flink_State_Backend {
public static void main(String[] args) throws IOException {
// 获取运行时环境 状态后端需要与开启Checkpoint一起使用
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
// 内存级别状态后端
env.setStateBackend(new MemoryStateBackend());
// 文件级别状态后端
env.setStateBackend(new FsStateBackend("hdfs://111.111.1.111:8020/flink/ck/fs"));
// RocksDB状态后端
env.setStateBackend(new RocksDBStateBackend("hdfs://111.111.1.111:8020/flink/ck/rocksdb"));
// 开启Checkpoint
env.getCheckpointConfig().enableUnalignedCheckpoints();
// Checkpoint 超时时间
env.getCheckpointConfig().setCheckpointTimeout(10000L);
// Checkpoint 时间间隔
env.getCheckpointConfig().setCheckpointInterval(15000L);
}
}
状态一致性
1、at-most-once(最多一次):故障之后,计数结果可能丢失。
2、at-least-once(至少一次):故障之后,可能多算,绝不会少算。
3、exactly-once(严格一次):故障后得到的计数结果与正确值一致
端到端的状态一致性
整个端到端的一致性级别取决于所有组件中一致性最弱的组件。
Source:需要外部源可重设数据的读取位置
Flink内部:checkpoint机制
Sink:1、幂等写入 2、事务性写入(预写日志【WAL】和两阶段提交【2PC】)
Flink的检查点
每个需要checkpoint的应用在启动时,Flink的JobManager为其创建一个 CheckpointCoordinator,CheckpointCoordinator全权负责本应用的快照制作。
流的分界线(barrier)是Flink的Checkpoint中的一个核心概念。
多个barrier被插入到数据流中, 然后作为数据流的一部分随着数据流动。这些barrier不会跨越流中的数据。每个barrier会把数据流分成两部分: 一部分数据进入当前的快照 , 另一部分数据进入下一个快照 。每个barrier携带着快照的id,barrier 不会暂停数据的流动。
对于barrier已经到达的分区,继续到达的数据会被缓存
而barrier尚未到达的分区,数据会被正常处理
Flink CheckPoint 和 SavePoint
public class Flink_State_WordCount {
public static void main(String[] args) throws Exception {
// 获取运行时环境
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
// 设置状态后端
env.setStateBackend(new FsStateBackend("hdfs://111.111.1.111:8020/flinktestdemo/ck"));
// 开启CK 间隔5s
env.enableCheckpointing(5000);
// 设置ck模式:严格一次
env.getCheckpointConfig().setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE);
// 设置任务 cancel 后 保留ck
env.getCheckpointConfig().enableExternalizedCheckpoints(CheckpointConfig.ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION);
// 读取数据并转换为元组
env.socketTextStream("111.111.1.111",9999)
.flatMap(new FlatMapFunction<String, Tuple2<String,Integer>>() {
@Override
public void flatMap(String value, Collector<Tuple2<String, Integer>> out) throws Exception {
for (String s : value.split(" ")) {
out.collect(Tuple2.of(s,1));
}
}
})
.keyBy(new KeySelector<Tuple2<String, Integer>, String>() {
@Override
public String getKey(Tuple2<String, Integer> value) throws Exception {
return value.f0;
}
})
.sum(1)
.print();
env.execute();
}
}
从SavePoint和CK恢复任务 案例:standalone模式
任务以正常模式进行关闭,checkpoint会正常删除,无法以ck恢复
//启动任务
bin/flink -m 111.111.1.111:8081 -c 全类名 xxx.jar
//保存点(只能手动)
bin/flink savepoint -m 111.111.1.111:8081 JobId hdfs://111.111.1.111:8020/flinktestdemo/save
//关闭任务并从保存点恢复任务
bin/flink run -s hdfs://111.111.1.111:8020/flinktestdemo/save/... -m 111.111.1.111:8081 -c 全类名 xxx.jar
//从CK位置恢复数据
env.getCheckpointConfig().enableExternalizedCheckpoints(CheckpointConfig.ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION);
bin/flink run -s hdfs://111.111.1.111:8020/flinktestdemo/ck/Jobid/chk-180 -m 111.111.1.111:8081 -c 全类名 xxx.jar
Flink + Kafka 实现端到端严格一次
Kafka Sink 内部已实现2PC,和跟checkpoint的交互