flink 状态编程和容错机制

流式计算分为无状态和有状态两种情况。无状态的计算观察每个独立事件,并
根据最后一个事件输出结果。例如,流处理应用程序从传感器接收温度读数,并在
温度超过 90 度时发出警告。有状态的计算则会基于多个事件输出结果。以下是一些
例子。
所有类型的窗口。例如,计算过去一小时的平均温度,就是有状态的计算。
所有用于复杂事件处理的状态机。例如,若在一分钟内收到两个相差 20
以上的温度读数,则发出警告,这是有状态的计算。
流与流之间的所有关联操作,以及流与静态表或动态表之间的关联操作,
都是有状态的计算。
下图展示了无状态流处理和有状态流处理的主要区别。无状态流处理分别接收
每条数据记录 ( 图中的黑条 ) ,然后根据最新输入的数据生成输出数据 ( 白条 ) 。有状态
流处理会维护状态 ( 根据每条输入记录进行更新 ) ,并基于最新输入的记录和当前的
状态值生成输出记录 ( 灰条 )

 

上图中输入数据由黑条表示。无状态流处理每次只转换一条输入记录,并且仅
根据最新的输入记录输出结果 ( 白条 ) 。有状态 流处理维护所有已处理记录的状态
值,并根据每条新输入的记录更新状态,因此输出记录 ( 灰条 ) 反映的是综合考虑多
个事件之后的结果。
尽管无状态的计算很重要,但是流处理对有状态的计算更感兴趣。事实上,正
确地实现有状态的计算比实现无状态的计算难得多。旧的流处理系统并不支持有状
态的计算,而新一代的流处理系统则将状态及其正确性视为重中之重。
1 有状态的算子和应用程序
Flink 内置的很多算子,数据源 source ,数据存储 sink 都是有状态的,流中的数
据都是 buffer records ,会保存一定的元素或者元数据。例如 : ProcessWindowFunction
会缓存输入流的数据, ProcessFunction 会保存设置的定时器信息等等。
Flink 中,状态始终与特定算子相关联。总的来说,有两种类型的状态:
算子状态( operator state
键控状态( keyed state
1 算子状态( operator state

 

 

Flink 为算子状态提供三种基本数据结构:
列表状态( List state
将状态表示为一组数据的列表。
联合列表状态( Union list state
也将状态表示为数据的列表。它与常规列表状态的区别在于,在发生故障时,或者从保
存点( savepoint )启动应用程序时如何恢复。
广播状态( Broadcast state
如果一个算子有多项任务,而它的每项任务状态又都相同,那么这种特殊情况最适合应
用广播状态。
2 键控状态( keyed state
键控状态是根据输入数据流中定义的键( key )来维护和访问的。 Flink 为每个键值维护
一个状态实例,并将具有相同键的所有数据,都分区到同一个算子任务中,这个任务会维护
和处理这个 key 对应的状态。当任务处理一条数据时,它会自动将状态的访问范围限定为当
前数据的 key 。因此,具有相同 key 的所有数据都会访问相同的状态。 Keyed State 很类似于
一个分布式的 key-value map 数据结构,只能用于 KeyedStream keyBy 算子处理之后)。

 

Flink Keyed State 支持以下数据类型:
ValueState<T> 保存单个的值,值的类型为 T
o get 操作 : ValueState.value()
o set 操作 : ValueState.update(T value)
ListState<T> 保存一个列表,列表里的元素的数据类型为 T 。基本操作如下:
o ListState.add(T value)
o ListState.addAll(List<T> values)
o ListState.get() 返回 Iterable<T>
o ListState.update(List<T> values)
MapState<K, V> 保存 Key-Value 对。
o MapState.get(UK key)
o MapState.put(UK key, UV value)
o MapState.contains(UK key)
o MapState.remove(UK key)
ReducingState<T>
AggregatingState<I, O>
State.clear() 是清空操作。
我们可以利用 Keyed State ,实现这样一个需求:检测传感器的温度值,如果连
续的两个温度差值超过 10 度,就输出报警。

 这里需要实现一个自定义的 RichFlatMapFuction,具体实现如下:

 

通过 RuntimeContext 注册 StateDescriptor StateDescriptor 以状态 state 的名字
和存储的数据类型为参数。
open() 方法中创建 state 变量。注意复习之前的 RichFunction 相关知识。
2 状态一致性
当在分布式系统中引入状态时,自然也引入了一致性问题。一致性实际上是 "
正确性级别 " 的另一种说法,也就是说在成功处理故障并恢复之后得到的结果,与没
有发生任何故障时得到的结果相比,前者到底有多正确?举例来说,假设要对最近
一小时登录的用户计数。在系统经历故障之后,计数结果是多少?如果有偏差,是
有漏掉的计数还是重复计数?
1 一致性级别
在流处理中,一致性可以分为 3 个级别:
at-most-once: 这其实是没有正确性保障的委婉说法 —— 故障发生之后,计
数结果可能丢失。同样的还有 udp
at-least-once: 这表示计数结果可能大于正确值,但绝不会小于正确值。也
就是说,计数程序在发生故障后可能多算,但是绝不会少算。
exactly-once: 这指的是系统保证在发生故障后得到的计数结果与正确值一
致。
曾经, at-least-once 非常流行。第一代流处理器 ( Storm Samza) 刚问世时只
保证 at-least-once ,原因有二。
保证 exactly-once 的系统实现起来更复杂。这在基础架构层 ( 决定什么代表
正确,以及 exactly-once 的范围是什么 ) 和实现层都很有挑战性。
流处理系统的早期用户愿意接受框架的局限性,并在应用层想办法弥补 (
如使应用程序具有幂等性,或者用批量计算层再做一遍计算 )
最先保证 exactly-once 的系统 (Storm Trident Spark Streaming) 在性能和表现力
这两个方面付出了很大的代价。为了保证 exactly-once ,这些系统无法单独地对每条
记录运用应用逻辑,而是同时处理多条 ( 一批 ) 记录,保证对每一批的处理要么全部
成功,要么全部失败。这就导致在得到结果前,必须等待一批记录处理结束。因此,
用户经常不得不使用两个流处理框架 ( 一个用来保证 exactly-once ,另一个用来对每
个元素做低延迟处理 ) ,结果使基础设施更加复杂。曾经,用户不得不在保证
exactly-once 与获得低延迟和效率之间权衡利弊。 Flink 避免了这种权衡。
Flink 的一个重大价值在于, 它既保证了 exactly-once ,也具有低延迟和高吞吐
的处理能力
从根本上说, Flink 通过使自身满足所有需求来避免权衡,它是业界的一次意义
重大的技术飞跃。尽管这在外行看来很神奇,但是一旦了解,就会恍然大悟。
(注:flink的概念相对spark更加抽象,很多概念不一样,不能用spark的思路去套flink,确实很大不同)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大数据开发工程师-宋权

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值