Flink状态编程

为什么状态很重要

Flink定义的状态

状态是计算的过程中需要保存的一些中间态,这些状态是需要我们手工编写代码去进行缓存以便后续使用的。

首先要理解状态的作用域:

  1. 任务:任务是Flink提交的一次作业,也就是说,所有的状态都是在一个任务里面的,任务结束的时候,所有的状态都会被清空
  2. 子任务:flink可以进行并行度的设置,所以在每个环节可能被拆为多个子任务,每个子任务的状态相互隔离,这也被称为算子状态。事实上,这样的隔离是我们正所需要的,因为每个子任务处理不同的数据,所以里面计算出来的状态值内容本身也可能不能。除非在一些特殊场景下,需要每个子任务的数据相同(比如读取一些配置,这是通过子任务的广播实现的)
  3. 链:flink是面向流的,数据流根据业务的诉求会被分成很多分流,用keyBy函数中定义Key进行划分,每个分流可以被认为是一个状态空间,这也被称为链控状态。flink内部为每个key都维护了一份实例

这也就是flink中的两种状态:算子状态链控状态。一般使用链控状态,因为处理的数据都是以key作为单位维度去处理的。

相关操作理解

理解获取运行上下文:getRuntimeContext

getRuntimeContext: 这个函数是获取运行时的上下文。因为flink是面向流的,所以数据要在里面
因为flink是面向流的,要给流动的数据进行缓存,这里flink有一个机制叫做获取上下文getRunTime
他的入参是一个状态描述符,这个类本身是继承于Serializable接口去存储状态,需要声明类型,如下

getRuntimeContext().getState(new valueStateDescriptor);

需求场景

场景1:跳变发出预警

若变化大于10,进行告警(常见风控、监控需求)
思路:保存上一段数据为一个状态,用当前的数据 - 上次保存的数据。如果大于阀值(10), 进行告警

val alertStream = dataStream
	.keyBt(_.id) // 当前器件的id
	.flatMap( new TempChangeAlert(10))
alertSream.print()

env,execute("start test")

// 实现
class TempChangeAlert(threshold: Double) extends RichFlatMapFunction[SensorReading, (String, Double, Double)]{
	// 定义状态保存上一次温度
	lazy val lastTempState: ValueState[Double] = getRuntimeContext.getState(new ValueStateDescripor[Double](""))

	override def flatMap(value: SensorReading, out: Collector[String])
	val lastTemp = lasteTempState.value()
	val diff = (value.temperature - lastTemp).abs
	if ( diff > threshold)
		out.collect(( value.id, lastTemp, value.temperature))
}

场景2:统计总接入的用户数

思路:在open阶段,打开一个状态描述器获取流中的信息,然后再map函数中生命一个hashset,将流中拿出的用户id添加到hashset里面

定义自己自己的richfunction,重写open和map函数

// 重写open函数,开辟区域存储状态
public void open() {
	stateDescriptor = new ValueStateDescripor<>(
	)
	myStateValue = getRuntimeContext().getState(stateDescriptor);
}

// 重写map函数,定义set结构体进行统计
public void map(Tuple2<String, Interger> tuple2){
	String id = tuple.f0;
	hashSet idSet = myStateValue.value();
	hashSet.add(id0;) 
    return hbaseMap;
}

算子探索

RichFunction

RichFunction是所有flink的函数的方法,可以获取运行环境的上下文,并拥有一些生命周期方法,所以可以实现更复杂的功能。在状态编程中是肯定会涉及到的。

可以看到RichFunction的底层,是继承于Funcion类,添加了以下几个方法
open:是RichFunction的初始化,
close:做一些清理
getRuntimeContext:例如函数执行的并行度,任务的名字,以及state状态
setRuntimeContext:设置函数的运行状态
getIterationRuntimeContext:未涉及
其他的AbstractRichFunctionRichMapFunctionRichSinkFunction都是基于以上进行扩展 。

使用

如果要操作有关生命周期相关的: 用RichXXXFunction, 或者直接用RichFunction自己添加接口; 如果要不操作与生命周期相关的: 直接使用map、reduce、flatmap等等方法

scala语法
var myVar : String = "Foo" // 声明一个变量
var z:Arrary[String] = new Array[String](3) // 声明一个数组
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值