李林超博客
首页
归档
留言
友链
动态
关于
归档
留言
友链
动态
关于
首页
大数据
正文
30.Flink状态一致性
Leefs
2022-02-13 PM
870℃
0条
[TOC] ### 前言 当在分布式系统中引入状态时,自然也引入了一致性问题。 状态一致性的本质就是**成功处理故障并恢复前后的结果的正确性级别。** 也就是说在成功处理故障并恢复之后得到的结果,与没有发生任何故障时得到的结果相比,前者到底有多正确? 举例来说,假设要对最近一小时登录的用户计数。在系统经历故障之后,计数结果是多少? 如果有偏差,是有漏掉的计数(最多一次)还是重复计数(最少一次)? ### 一、一致性级别 在流处理中,一致性可以分为三个级别: + **at-most-once(最多一次)**:当任务故障时,最简单的做法是什么都不干,既不恢复丢失的状态,也不重播丢失的数据。At-most-once语义的含义是最多处理一次事件。 + **at-least-once(至少一次)**:这表示计数结果可能大于正确值,但绝不会小于正确值。也就是说,计数程序在发生故障后可能多算,但是绝不会少算。 + **exactly-once(精确一次)**:恰好处理一次是最严格的保证,也是最难实现的。恰好处理一次语义不仅仅意味着没有事件丢失,还意味着针对每一个数据,内部状态仅仅更新一次。 Flink的一个重大价值在于,**它既保证了exactly-once,也具有低延迟和高吞吐的处理能力。** ### 二、端到端(end-to-end)状态一致性 目前我们看到的一致性保证都是由流处理器实现的,也就是说**都是在Flink流处理器内部保证的**; 而在真实应用中,流处理应用除了流处理器以外还包含了数据源(例如 Kafka)和输出到持久化系统。 即端到端一致性指的是从Source-Flink内部程序-Sink持久化系统,状态的一致性即结果的正确性贯穿了整个流处理应用的始终。 每一个组件都保证了它自己的一致性,**整个端到端的一致性级别取决于所有组件中一致性最弱的组件。** **具体可以划分如下:** + **内部保证**:依赖checkpoint + **source端**:需要外部源可重设数据的读取位置(kafka的offset) + **sink端**:需要保证从故障恢复时,数据不会重复写入外部系统 **而对于sink端,又有两种具体的实现方式:** + 幂等(Idempotent)写入。 + 事务性(Transactional)写入。 #### 幂等写入 所谓幂等操作,是说一个操作,可以重复执行很多次,但只导致一次结果更改,也就是说,后面再重复执行就不起作用了。 但是它的结果会有一个渐变的流程,例如求最大温度: **1->2->10**,此时故障从上一检查点处重新计算,**2->10->12**。最终的Sink数据流为**1->2->10->2->10->12**。虽然最终结果无误,但是流程看起来不好,如果这些数据要实时展示,则会给人误解。 #### 事务性写入 需要构建事务来写入外部系统,构建的事务对应着checkpoint,等到checkpoint真正完成的时候,才把所有对应的结果写入 sink 系统中。 对于事务性写入,具体又有两种实现方式:**预写日志(WAL)和两阶段提交(2PC)。** `DataStream API`提供了`GenericWriteAheadSink`模板类和`TwoPhaseCommitSinkFunction` 接口,可以方便地实现这两种方式的事务性写入。 **注意** + 预写日志(Write-Ahead-Log,WAL)并不是真正的`exactly-once`,当批量写入Sink时,如果中途出错,从checkpoint回放数据,则会导致数据重复插入; + 两阶段提交(2PC)才是真正的`exactly-once`,但是它需要写入的系统支持事务,并且事务的超时时间最好和checkpoint的超时时间一致。 **预写日志(Write-Ahead-Log,WAL)** + 把结果数据先当成状态保存,然后在收到checkpoint完成的通知时, 一次性写入sink系统; + 简单易于实现,由于数据提前在状态后端中做了缓存,所以无论什么 sink 系统,都能用这种方式一批搞定; + `DataStream API`提供了一个模板类:`GenericWriteAheadSink`,来实现这种事务性sink。 **两阶段提交(Two-Phase-Commit,2PC)** + 对于每个checkpoint,sink 任务会启动一个事务,并将接下来所有接收的数据添加到事务里; + 然后将这些数据写入外部 sink 系统,但不提交它们 —— 这时只是 “预提交”; + 当它收到 checkpoint 完成的通知时,它才正式提交事务,实现结果的真正写入 ; + 这种方式真正实现了 exactly-once,它需要一个提供事务支持的外部 sink 系统; + Flink提供了 `TwoPhaseCommitSinkFunction` 接口。 **要求** (1)外部sink系统必须提供事务支持,或者sink任务必须能够模拟外部系统上的事务; (2)在checkpoint的间隔期间里,必须能够开启一个事务并接受数据写入; (3)在收到checkpoint完成的通知之前,事务必须是“等待提交”的状态。在故障恢复的情况下,这可能需要一些时间。如果这个时候sink系统关闭事务(例如超时了),那么未提交的数据就会丢失; (4)sink任务必须能够在进程失败后恢复事务; (5)提交事务必须是幂等操作 ### 三、不同 Source 和 Sink 的一致性保证 ![30.Flink状态一致性01.png](https://lilinchao.com/usr/uploads/2022/02/3594468118.png) ### 四、Flink+Kafka端到端状态一致性的保证 + **内部**:利用 checkpoint 机制,把状态存盘,发生故障的时候以恢复,保证内部的状态一致性 + **source**: `kafka consumer`作为source,可以将偏移量保存下来, 如果后续任务出现了故障,恢复的时候可以由连接器重置偏移量,重新消费数据,保证一致性 + **sink**: `kafka producer`作为sink,采用两阶段提交sink,需要实现一个`TwoPhaseCommitSinkFunction` *附参考文章链接:* *https://awslzhang.top/2021/01/02/Flink%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86/*
标签:
Flink
非特殊说明,本博所有文章均为博主原创。
如若转载,请注明出处:
https://lilinchao.com/archives/1888.html
上一篇
29.Flink状态后端(State Backends)
下一篇
31.Flink容错机制介绍
取消回复
评论啦~
提交评论
栏目分类
随笔
2
Java
326
大数据
229
工具
31
其它
25
GO
47
标签云
Jenkins
GET和POST
Beego
Scala
MyBatis-Plus
Filter
Git
Spark Core
Kibana
Hbase
微服务
Elasticsearch
正则表达式
Spring
设计模式
工具
nginx
Hadoop
Flink
算法
机器学习
Docker
Golang基础
线程池
数据结构和算法
Hive
RSA加解密
JavaScript
Java工具类
ClickHouse
友情链接
申请
范明明
庄严博客
Mx
陶小桃Blog
虫洞