状态编程和容错机制(二)

状态编程和容错机制(二)

在上一篇博客中我们了解的Flink的状态编程概念和三种状态(算子状态、广播状态、键控状态)。我们知道Flink中的状态其实是一种中间值存储技术。那么当系统故障之后状态值该怎么取呢?这就要用到状态一致性机制。

状态一致性

为了解决系统故障之后我们无法确定数据准确性的问题,我们引入了状态一致性的概念。

状态一致性可以分为三种级别,分别是:

  • at-most-once:位于这个级别的系统其实是没有一致性保证的。也就是说故障恢复后是会出现数据丢失的。
  • at-least-once:位于这个级别的系统不会出现数据丢失现象,但是会出现重复计算的问题。
  • exactly-once:位于这个级别的系统故障之后的状态与故障之前的状态保持一致性。即计算结果不会多也不会少,是正确结果。

其实,Flink并不是首先实现exactly-once的架构。在它之前Spark-Streaming已经实现了exactly-once,但是,代价是巨大的。Spark-Streaming为了实现exactly-once而不能对每一条数据进行处理,只能通过批处理的方式,一批数据要么全部成功要么全部失败。这样做就牺牲掉了部分的性能优势。

Flink非常大的优势之一就是它即实现了exactly-once,又保证了低延迟和高吞吐量。

状态一致性原理

Flink实现状态一致性的原理其实很容易理解,我们可以称它为端到端的状态一致性。

我们可以把这个过程分成三部分:

  • 内部保证:通过检查点(check point)方式实现。具体什么是检查点咱们下边会讲。
  • source端:需要保证外部源可重置数据的读取位置。
  • sink端:需要保证故障恢复后不会输出重复数据。

在sink端有两种实现方式,分别是:

  • 幂等写入:可以重复写入多次,但是只执行一次修改,后面重复的数据不再执行修改。
  • 事务写入:需要构建事务来写入外部系统。事务需要与检查点对应,当检查点完成后才能执行事务。

Flink中将事务写入分成了两种,分别是

  • 预写日志(WAL);
  • 二阶段提交(2PC)

在这里插入图片描述

check point

Flink内部是通过check point来保证exactly-once的,接下来我们来看一下check point的执行过程。

初始状态:

在这里插入图片描述

保存source位置:

在这里插入图片描述

在这里插入图片描述

保存状态值:

在这里插入图片描述

当一个节点挂掉:

在这里插入图片描述

将输入流倒回到上一个检查点:

在这里插入图片描述

检查点是Flink最有价值的创新之一。它使Flink能够实现exactly-once并且不需要牺牲性能。

Flink+Kafka的exactly-once实现方式

Flink对Kafka即支持kafka source,也支持kafka sink。我们知道Flink内部是通过检查点的方式实现exactly-once的。那么Flink与Kafka之间是怎样实现exactly-once的呢?

  • source:kafka consumer作为source,可以将偏移量保存下来,如果后续任务出现了故障,恢复的时候可以由连接器重置偏移量,重新消费数据,保证一致性
  • sink:kafka producer作为sink,采用二段式提交。

具体实现方式如下图:

当检查点执行时,JobManager会将检查点分界线(barrier)注入到数据流。barrier会在算子之间传递。

在这里插入图片描述

当source检测到barrier之后会将偏移量(offset)作为状态保存到状态后端。下次从check point恢复时source会重新提交offset,从上次保存的位置开始重新消费数据。

在这里插入图片描述

内部算子检测到barrier会将状态提交的StateBackend。

sink会先将数据写入外部kafka,当sink检测到barrier之后会将状态保存的StateBackend并开启新的预提交任务。

在这里插入图片描述

当所有的算子任务完成快照,即这次检查点完成之后,JobManager会向所有的算子发送完成通知。

sink接收到通知后,会将预提交事务提交。这样之前预提交的数据就正式确认提交了。

在这里插入图片描述

状态后端类型

Flink官方列举了三种类型的状态后端,分别是:

  • MemoryStateBackend:这种方式会将检查点状态存放到JobManager的内存中;将每个算子的状态存放在其所在节点的taskManager的JVM堆中。
  • FsStateBackend:这种方式会将检查点状态存放到指定的文件系统中;算子状态与MemoryStateBackend一样。
  • RocksDBStateBackend:将所有的状态信息序列化后保存到本地的RocksDB数据库。

修改flink-conf.yarm设置默认状态后端:

state.backend: filesystem
state.checkpoints.dir: hdfs://namenode:40010/flink/checkpoints

程序中指定状态后端:

StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setStateBackend(new FsStateBackend("hdfs://namenode:40010/flink/checkpoints"));
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值