flink状态编程

author author     2023-03-14     705

关键词:

参考技术A 1.流式计算分为无状态和有状态两种情况。 无状态的计算观察每个独立事件,并根据最后一个事件输出结果。例如,流处理应用程序从传感器接收水位数据,并在水位超过指定高度时发出警告。有状态的计算则会基于多个事件输出结果。以下是一些例子。

(1)所有类型的窗口。例如,计算过去一小时的平均水位,就是有状态的计算。

(2)所有用于复杂事件处理的状态机。例如,若在一分钟内收到两个相差20cm以上的水位差读数,则发出警告,这是有状态的计算。

(3)流与流之间的所有关联操作,以及流与静态表或动态表之间的关联操作,都是有状态的计算。

2.下图展示了无状态流处理和有状态流处理的主要区别。 无状态流处理分别接收每条数据记录(图中的黑条),然后根据最新输入的数据生成输出数据(白条)。有状态流处理会维护状态(根据每条输入记录进行更新),并基于最新输入的记录和当前的状态值生成输出记录(灰条)。

上图中输入数据由黑条表示。无状态流处理每次只转换一条输入记录,并且仅根据最新的输入记录输出结果(白条)。有状态 流处理维护所有已处理记录的状态值,并根据每条新输入的记录更新状态,因此输出记录(灰条)反映的是综合考虑多个事件之后的结果。

3.有状态的算子和应用程序

Flink内置的很多算子,数据源source,数据存储sink都是有状态的,流中的数据都是buffer records,会保存一定的元素或者元数据。例如: ProcessWindowFunction会缓存输入流的数据,ProcessFunction会保存设置的定时器信息等等。

在Flink中,状态始终与特定算子相关联。总的来说,有两种类型的状态:

算子状态(operator state)

键控状态(keyed state)

4.算子状态(operator state)

算子状态的作用范围限定为算子任务。这意味着由同一并行任务所处理的所有数据都可以访问到相同的状态,状态对于同一任务而言是共享的。算子状态不能由相同或不同算子的另一个任务访问。

Flink为算子状态提供三种基本数据结构:

列表状态(List state):将状态表示为一组数据的列表。

联合列表状态(Union list state):也将状态表示为数据的列表。它与常规列表状态的区别在于,在发生故障时,或者从保存点(savepoint)启动应用程序时如何恢复。

广播状态(Broadcast state):如果一个算子有多项任务,而它的每项任务状态又都相同,那么这种特殊情况最适合应用广播状态

5.键控状态(keyed state)

键控状态是根据输入数据流中定义的键(key)来维护和访问的。Flink为每个键值维护一个状态实例,并将具有相同键的所有数据,都分区到同一个算子任务中,这个任务会维护和处理这个key对应的状态。当任务处理一条数据时,它会自动将状态的访问范围限定为当前数据的key。因此,具有相同key的所有数据都会访问相同的状态。Keyed State很类似于一个分布式的key-value map数据结构,只能用于KeyedStream(keyBy算子处理之后)。

6.状态后端(state backend)

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

状态后端主要负责两件事:

1)本地的状态管理

2)将检查点(checkpoint)状态写入远程存储

状态后端分类:

(1)MemoryStateBackend

内存级的状态后端,会将键控状态作为内存中的对象进行管理,将它们存储在TaskManager的JVM堆上;而将checkpoint存储在JobManager的内存中。

(2)FsStateBackend

将checkpoint存到远程的持久化文件系统(FileSystem)上。而对于本地状态,跟MemoryStateBackend一样,也会存在TaskManager的JVM堆上。

(3)RocksDBStateBackend

将所有状态序列化后,存入本地的RocksDB中存储。

7.状态一致性

当在分布式系统中引入状态时,自然也引入了一致性问题。一致性实际上是"正确性级别"的另一种说法,也就是说在成功处理故障并恢复之后得到的结果,与没有发生任何故障时得到的结果相比,前者到底有多正确?举例来说,假设要对最近一小时登录的用户计数。在系统经历故障之后,计数结果是多少?如果有偏差,是有漏掉的计数还是重复计数?

1)一致性级别

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

(1) at-most-once : 这其实是没有正确性保障的委婉说法——故障发生之后,计数结果可能丢失。同样的还有udp。

(2) at-least-once : 这表示计数结果可能大于正确值,但绝不会小于正确值。也就是说,计数程序在发生故障后可能多算,但是绝不会少算。

(3) exactly-once : 这指的是系统保证在发生故障后得到的计数结果与正确值一致。

曾经,at-least-once非常流行。第一代流处理器(如Storm和Samza)刚问世时只保证at-least-once,原因有二。

(1)保证exactly-once的系统实现起来更复杂。这在基础架构层(决定什么代表正确,以及exactly-once的范围是什么)和实现层都很有挑战性。

(2)流处理系统的早期用户愿意接受框架的局限性,并在应用层想办法弥补(例如使应用程序具有幂等性,或者用批量计算层再做一遍计算)。

最先保证exactly-once的系统(Storm Trident和Spark Streaming)在性能和表现力这两个方面付出了很大的代价。为了保证exactly-once,这些系统无法单独地对每条记录运用应用逻辑,而是同时处理多条(一批)记录,保证对每一批的处理要么全部成功,要么全部失败。这就导致在得到结果前,必须等待一批记录处理结束。因此,用户经常不得不使用两个流处理框架(一个用来保证exactly-once,另一个用来对每个元素做低延迟处理),结果使基础设施更加复杂。曾经,用户不得不在保证exactly-once与获得低延迟和效率之间权衡利弊。Flink避免了这种权衡。

Flink的一个重大价值在于, 它既保证了 exactly-once ,也具有低延迟和高吞吐的处理能力 。

从根本上说,Flink通过使自身满足所有需求来避免权衡,它是业界的一次意义重大的技术飞跃。尽管这在外行看来很神奇,但是一旦了解,就会恍然大悟。

2)端到端(end-to-end)状态一致性

目前我们看到的一致性保证都是由流处理器实现的,也就是说都是在 Flink 流处理器内部保证的;而在真实应用中,流处理应用除了流处理器以外还包含了数据源(例如 Kafka)和输出到持久化系统。

端到端的一致性保证,意味着结果的正确性贯穿了整个流处理应用的始终;每一个组件都保证了它自己的一致性,整个端到端的一致性级别取决于所有组件中一致性最弱的组件。具体可以划分如下:

1)source端 —— 需要外部源可重设数据的读取位置

2)link内部 —— 依赖checkpoint

3)sink端 —— 需要保证从故障恢复时,数据不会重复写入外部系统

而对于sink端,又有两种具体的实现方式:幂等(Idempotent)写入和事务性(Transactional)写入。

4)幂等写入

所谓幂等操作,是说一个操作,可以重复执行很多次,但只导致一次结果更改,也就是说,后面再重复执行就不起作用了。

5)事务写入

需要构建事务来写入外部系统,构建的事务对应着 checkpoint,等到 checkpoint 真正完成的时候,才把所有对应的结果写入 sink 系统中。

对于事务性写入,具体又有两种实现方式:预写日志(WAL)和两阶段提交(2PC)。

8.检查点(checkpoint)

Flink具体如何保证exactly-once呢? 它使用一种被称为"检查点"(checkpoint)的特性,在出现故障时将系统重置回正确状态。下面通过简单的类比来解释检查点的作用。

9.Flink+Kafka如何实现端到端的exactly-once语义

我们知道,端到端的状态一致性的实现,需要每一个组件都实现,对于Flink + Kafka的数据管道系统(Kafka进、Kafka出)而言,各组件怎样保证exactly-once语义呢?

1)内部 —— 利用checkpoint机制,把状态存盘,发生故障的时候可以恢复,保证内部的状态一致性

2)source —— kafka consumer作为source,可以将偏移量保存下来,如果后续任务出现了故障,恢复的时候可以由连接器重置偏移量,重新消费数据,保证一致性

3)sink —— kafka producer作为sink,采用两阶段提交 sink,需要实现一个TwoPhaseCommitSinkFunction

内部的checkpoint机制我们已经有了了解,那source和sink具体又是怎样运行的呢?接下来我们逐步做一个分析。

我们知道Flink由JobManager协调各个TaskManager进行checkpoint存储,checkpoint保存在 StateBackend中,默认StateBackend是内存级的,也可以改为文件级的进行持久化保存。

当checkpoint 启动时,JobManager 会将检查点分界线(barrier)注入数据流;barrier会在算子间传递下去。

每个算子会对当前的状态做个快照,保存到状态后端。对于source任务而言,就会把当前的offset作为状态保存起来。下次从checkpoint恢复时,source任务可以重新提交偏移量,从上次保存的位置开始重新消费数据。

每个内部的transform 任务遇到 barrier 时,都会把状态存到 checkpoint 里。

sink 任务首先把数据写入外部 kafka,这些数据都属于预提交的事务(还不能被消费);当遇到 barrier 时,把状态保存到状态后端,并开启新的预提交事务。

当所有算子任务的快照完成,也就是这次的 checkpoint 完成时,JobManager 会向所有任务发通知,确认这次 checkpoint 完成。

当sink 任务收到确认通知,就会正式提交之前的事务,kafka 中未确认的数据就改为“已确认”,数据就真正可以被消费了。

所以我们看到,执行过程实际上是一个两段式提交,每个算子执行完成,会进行“预提交”,直到执行完sink操作,会发起“确认提交”,如果执行失败,预提交会放弃掉。

具体的两阶段提交步骤总结如下:

1)第一条数据来了之后,开启一个 kafka 的事务(transaction),正常写入 kafka 分区日志但标记为未提交,这就是“预提交”

2)触发 checkpoint 操作,barrier从 source 开始向下传递,遇到 barrier 的算子将状态存入状态后端,并通知jobmanager

3)sink 连接器收到 barrier,保存当前状态,存入 checkpoint,通知 jobmanager,并开启下一阶段的事务,用于提交下个检查点的数据

4)jobmanager 收到所有任务的通知,发出确认信息,表示 checkpoint 完成

5)sink 任务收到 jobmanager 的确认信息,正式提交这段时间的数据

6)外部kafka关闭事务,提交的数据可以正常消费了。

flink基础:状态编程(代码片段)

1简介  流式计算分为无状态和有状态两种情况。无状态的计算观察每个独立事件,并根据最后一个事件输出结果。例如,流处理应用程序从传感器接收温度读数,并在温度超过90度时发出警告。有状态的计算则会基于多个事件... 查看详情

flink-使用flink处理函数以及状态编程实现topn案例(代码片段)

7.5应用案例-TopN7.5.1使用ProcessAllWindowFunction场景例如,需要统计最近10秒内最热门的两个url链接,并且每5秒思路使用全窗口函数ProcessAllWindowFunction开窗处理,使用HashMap来保存每个url的访问次数(通过遍历)然后转成ArrayList,然后... 查看详情

flink状态编程

参考技术A1.流式计算分为无状态和有状态两种情况。无状态的计算观察每个独立事件,并根据最后一个事件输出结果。例如,流处理应用程序从传感器接收水位数据,并在水位超过指定高度时发出警告。有状态的计算则会基于多... 查看详情

flink学习flink的核心语义和架构模型

...一个表;而无界流指的是数据随着时间增加而增长,计算状态持续进行,比如我们消费Kafka中的消息,消息持续不断,那么计算也会持续进行不会结束。State(状态),所谓的状态指的是在进行流式计算过程中的信息。一般用作... 查看详情

apacheflink:数据流编程模型

...据流,并行数据流,窗口,时间概念,有状态计算,容错检查点。|抽象层级Flink提供不同级别的抽象来开发流/批处理应用程序。最低级抽象只提供有状态流。它通过ProcessFunction嵌入到DataStreamAPI中。它允许用户... 查看详情

flink状态管理

大家好,我是小寒~原文链接:Flink的状态管理2022大数据学习路线图在上一篇文章,我们分享了FLink中时间和窗口的相关技术细节,今天我们来分享一下FLink中的状态管理相关的内容。状态管理状态在FLink中叫作State,用来保存中间... 查看详情

大数据(9d)flink流处理核心编程练习:计算pv和uv(代码片段)

...pom.xmllog4j.propertiesPV计算UV计算UV计算优化:使用键控状态概述本地开发环境(WIN10+IDEA)(本文代码可作为Flink之Transform练习模板,在#####################################之间修改业务逻辑)计算P 查看详情

13-flink-1.10.1-flink状态管理(代码片段)

目录1Flink中的状态2算子状态(OperatorState) 2.1算子状态类型3键控状态(keyedState) 3.1 键控状态数据结构3.2 键控状态使用3.3 实例3.3.1第一种实现方式3.3.2第二种实现方式1Flink中的状态由一... 查看详情

13-flink-1.10.1-flink状态管理(代码片段)

目录1Flink中的状态2算子状态(OperatorState) 2.1算子状态类型3键控状态(keyedState) 3.1 键控状态数据结构3.2 键控状态使用3.3 实例3.3.1第一种实现方式3.3.2第二种实现方式1Flink中的状态由一... 查看详情

有状态流处理:flink状态后端

...Flink系统性学习笔记Flink1.12.0这篇文章我们将深入探讨有状态流处理,更确切地说是Flink中可用的不同状态后端。在以下部分,我们将介绍Flink的3个状态后端,看一下它们的局限性以及如何根据具体案例需求选择最合适的状态后端... 查看详情

flink官方社区系列视频教程

1.ApacheFlink系列教程-入门篇1.为什么要学习ApacheFlink?2.ApacheFlink概念介绍:有状态流式处理引擎的基石3.ApacheFlink安装部署、环境配置及运行应用程序4.ApacheFlinkDataStreamAPI编程</ 查看详情

flink官方社区系列视频教程

1.ApacheFlink系列教程-入门篇1.为什么要学习ApacheFlink?2.ApacheFlink概念介绍:有状态流式处理引擎的基石3.ApacheFlink安装部署、环境配置及运行应用程序4.ApacheFlinkDataStreamAPI编程</ 查看详情

Flink 用于无状态处理

】Flink用于无状态处理【英文标题】:FlinkforStatelessprocessing【发布时间】:2021-03-2014:32:34【问题描述】:我是flink的新手,我们的用例涉及无状态计算。读取事件、处理事件并持久化到数据库中。但Flink文档从未提及无状态处理。... 查看详情

flink-状态与容错-broadcaststate--flink1.13(代码片段)

文章目录一、广播状态介绍1.1、什么是广播状态1.2、广播状态的动态模型评估三、API介绍3.1、BroadcastProcessFunction和KeyedBroadcastProcessFunction3.2、重要注意事项四、案例-实现配置动态更新4.1、逻辑步骤4.2、代码实现参考:Flink从1.5.0... 查看详情

flink之状态之checkpointing(代码片段)

1.前言在Flink中,函数和操作符都可以是有状态的。在处理每个消息或者元素时,有状态的函数都会储存信息,使得状态成为精密操作中关键的组成部分。为了使状态能够容错,Flink会checkpoints状态。checkpoints机制使得Flink可以恢复... 查看详情

15-flink-1.10.1-flink状态后端(代码片段)

1状态后端保存状态有专门的一个组件来做。不需要我们额外开发 2   选择一种方式的状态后端需要根据自己的业务需要选择一种适合自己的状态后端方式3状态后端的设置3.1 MemoryStateBackendenv.setStateBackend(newMemoryStateBackend())//Memo... 查看详情

15-flink-1.10.1-flink状态后端(代码片段)

1状态后端保存状态有专门的一个组件来做。不需要我们额外开发 2   选择一种方式的状态后端需要根据自己的业务需要选择一种适合自己的状态后端方式3状态后端的设置3.1 MemoryStateBackendenv.setStateBackend(newMemoryStateBackend())//Memo... 查看详情

有状态流处理:flink状态后端

...Flink系统性学习笔记Flink1.12.0这篇文章我们将深入探讨有状态流处理,更确切地说是Flink中可用的不同状态后端。在以下部分,我们将介绍Flink的3个状态后端,看一下它们的局限性以及如何根据具体案例需求选择最合适的状态后端... 查看详情