文章目录

  • 容错机制
  • 6.4.4 状态一致性
  • 6.4.4.1一致性级别
  • 6.4.4.2 端到端的状态一致性——如何保证精准一次新消费
  • 6.4.4.2.1 幂等写入
  • 6.4.4.2.2 事务写入
  • ①预写日志(WAL)
  • ②两阶段提交(2PC)
  • 6.4.5 检查点 —— checkpoint
  • ①flink检查点算法——Chandy-Lamport 算法的分布式快照
  • ②barrier对齐
  • ③barrier不对齐
  • ④Flink+Kafka 如何实现端到端的Exactly-Once语义
  • **随笔**
  • 6.4.6 保存点


容错机制

6.4.4 状态一致性

6.4.4.1一致性级别

在流处理中,一致性可以分为3个级别

1.at-most-once:
	这其实是没有正确性保障的委婉说法—故障发生后,计数结果可能丢失,同样的还有udp
2.at-least-once:("最少一次")
	这表示计数结果可能大于正确值,但绝不会小于正确值,也就是说,计数程序在发生故障后可能多算,但是绝不会少算。
3.exactly-once:("精准一次")
	这指的是系统保证在发生故障后得到的计数结果与正确值一致。
	
--Flink的一个重大价值在于,它既保证了exactly-once,也具有低延迟和高吞吐的处理能力。
--从根本上说,Flink通过使自身满足所有需求来避免权衡。
6.4.4.2 端到端的状态一致性——如何保证精准一次新消费
整个端到端的一致性级别取决于所有组件中一致性最弱的组件
具体可以划分如下:
	source端 ———— 需要外部源可重设数据的读取位置
	flink内部 ———— 依赖checkpoint
	sink端 ———— 需要保证从故障恢复时,数据不会重复写入外部系统
	而对于sink端,又有两种具体实现方式:
 		'幂等写入'和'事务写入'
 					事务写入有两种方式:预写日志和两阶段提交
6.4.4.2.1 幂等写入
幂等操作,是说一个操作,可以重复执行很多次,但只导致一次结果更改,也就是说,后面再重复执行就不起作用了。


flink 决策数 flink精准一次_flink 决策数

6.4.4.2.2 事务写入
需要构建事务来写入外部系统,构建的事务对应着checkpoint,等到checkpoint真正完的时候,才把所有对应的结果写入sink系统中,对于事务性写入,具体又有两种实现方式:预写日志(WAL)和两阶段提交(2PC)


flink 决策数 flink精准一次_幂等_02

①预写日志(WAL)
预写日志(Write-Ahead-Log)
1)把结果数据先当成状态保存,然后收到checkpoint完成的通知时,一次性写入sink系统。
2)由于数据提前在状态后端(state backend)中做了缓存,所以无论什么 sink 系统,都能用这种方式一批搞定
3)DataStream API提供了一个模板类:GenericWriteAheadSink来实现这种事务性sink
②两阶段提交(2PC)
两阶段提交two-parse commit
1)对于每个checkpoint,sink任务会启动一个事务,并将接下来所有接收的数据添加到事务里。
2)将这些数据写入外部sink系统,但是不提交它们,只是“预提交”。
3)当它收到checkpoint完成的通知时,才正式提交事务,实现结果的真正写入。
4)这种方式真正实现了exactly-once。
5)这种方式真正实现了exactly-once,它需要一个提供事务支持的外部sink系统,Flink提供了TwoPhaseCommitSinkFunction接口。
TwoPhaseCommitSink对外部sink系统的要求
1)外部 sink 系统必须提供事务支持,或者 sink 任务必须能够模拟外部系统上的事务
2)在 checkpoint 的间隔期间里,必须能够开启一个事务并接受数据写入
3)在收到 checkpoint 完成的通知之前,事务必须是“等待提交”的状态。
	在故障恢复的情况下,这可能需要一些时间。如果这个时候sink系统关闭事务(例如超时了),那么未提交的数据就会丢失
4)sink 任务必须能够在进程失败后恢复事务
5)提交事务必须是幂等操作

总结

DataStream API 提供了GenericWriteAheadSink模板类和TwoPhaseCommitSinkFunction 接口,可以方便地实现这两种方式的事务性写入。 不同 Source 和 Sink 的一致性保证可以用下表说明:

flink 决策数 flink精准一次_幂等_03

'幂等会出现暂时不一致:'
	是指一批数据回滚后,在发生故障前这批数据已经有写入sink的了,回滚会重新重播这部分数据,但是它是幂等操作,所以还是保证了Exactly-once。

6.4.5 检查点 —— checkpoint

作用

为了保证精准一次性消费

①flink检查点算法——Chandy-Lamport 算法的分布式快照

Flink检查点的核心作用是确保状态正确,即使遇到程序中断,也要正确。记住这一基本点之后,Flink为用户提供了用来定义状态的工具。

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 收集齐所有的state handle,就认为这一次的checkpoint全局完成了,向持久化存储中灾备份一个checkpoint meta文件

flink 决策数 flink精准一次_flink_04

②barrier对齐

flink 决策数 flink精准一次_检查点_05

1.一旦 Operator 从输入流接收到 CheckPointbarrier n,它就不能处理来自该流的任何数据记录,直到它从其他所有输入接收到 barrier n 为止。否则,它会混合属于快照 n 的记录和属于快照 n + 1 的记录。
	2.接收到 barrier n 的流暂时被搁置。从这些流接收的记录不会被处理,而是放入输入缓冲区。
	3.上图中第 2 个图,虽然数字流对应的 barrier 已经到达了,但是 barrier 之后的 1、2、3 这些数据只能放到 buffer 中,等待字母流的 barrier 到达。
	4.一旦最后所有输入流都接收到 barrier n,Operator 就会把缓冲区中 pending 的输出数据发出去,然后把 CheckPoint barrier n 接着往下游发送。这里还会对自身进行快照。
	5.之后,Operator 将继续处理来自所有输入流的记录,在处理来自流的记录之前先处理来自输入缓冲区的记录。
③barrier不对齐
1.上述图 2 中,当还有其他输入流的 barrier 还没有到达时,会把已到达的 barrier 之后的数据 1、2、3 搁置在缓冲区,等待其他流的 barrier 到达后才能处理。
	2.barrier 不对齐就是指当还有其他流的 barrier 还没到达时,为了不影响性能,也不用理会,直接处理 barrier 之后的数据。等到所有流的 barrier 的都到达后,就可以对该 Operator 做 CheckPoint 了。
Exactly Once 时必须 barrier 对齐,如果 barrier 不对齐就变成了 At Least Once。
④Flink+Kafka 如何实现端到端的Exactly-Once语义
1.第一条数据来了之后,开启一个kafka的事务(transaction),正常写入kafka分区日志,单标记为未提交,这就是“预提交”
	2.jobmanager触发checkpoint操作,barrier从source开始向下传递,遇到barrier的算子将状态存入状态后端,并通知jobmanager
	3.sink连接器收到barrier,保存当前状态,存入checkpoint,通知jobmanager,并开启下一阶段事务,用于提交下一个检查点的数据
	4.jobmanager收到所有任务的通知,发出确认小子,表示checkpoint完成
	5.sink收到jobmanager的确认信息,正式提交这段时间的数据
	6.外部kafka关闭事务,提交的数据就可以正常消费了。
随笔
--------------------------------------------------------------------------------------------------------------------------------
checkpoint配置
    env.getCheckpointConfig.setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE)
    env.getCheckpointConfig.setCheckpointTimeout(300000L)				// ck执行多久超时
    env.getCheckpointConfig.setMaxConcurrentCheckpoints(2)				// 异步ck,同时有几个ck在执行
    env.getCheckpointConfig.setMinPauseBetweenCheckpoints(500L)			// 上一个ck结束后,到下一个ck开启,最小间隔多久
    env.getCheckpointConfig.setPreferCheckpointForRecovery(false)		// 默认为 false,表示从 ck恢复;true,从savepoint恢复
    env.getCheckpointConfig.setTolerableCheckpointFailureNumber(3)		// 允许当前checkpoint失败的次数
--------------------------------------------------------------------------------------------------------------------------------
1.flink中的检查点,保存的是所有任务状态的快照
这个状态要求是所有任务都处理同一个数据之后的状态

2. flink checkpoint算法
基于 Chandy-Lamport 算法的分布式快照

3. flink checkpoint中重要的概念
barrier用于分隔不同的checkpoint,对于每个任务而言,收到barrier就意味着要开始做state的保存
算子中需要对不同上游分区发来的barrier,进行对齐

4. checkpoint存储位置,由state backend决定
一般是放在远程持久化存储空间
jobmanager触发一个checkpoint操作,会把checkpoint中所有任务状态的拓扑结构保存下来

5. barrier和watermark类似,都可以看作一个插入数据流中的特殊数据结构
barrier在数据处理上跟watermark是两套机制,完全没有关系

6.4.6 保存点

1、Flink 还提供了可以自定义的镜像保存功能,就是保存点(savepoints)
2、原则上,创建保存点使用的算法与检查点完全相同,因此保存点可以认为就是具有一些额外元数据的检查点
3、Flink不会自动创建保存点,因此用户(或外部调度程序)必须明确地触发创建操作 
4、保存点是一个强大的功能。除了故障恢复外,保存点可以用于:有计划的手动备份,更新应用程序,版本迁移,暂停和重启应用,等等