Flink从入门到真香(15、Flink状态管理)

```由一个任务维护,并且用来计算某个结果的所有数据,都属于这个任务的状态
可以认为状态就是一个本地变量,可以被任务的业务逻辑访问
Flink会进行状态管理,包括状态一致性、故障处理以及高效存储和访问,以便开发人员可以专注于应用程序的逻辑


![](https://s4.51cto.com/images/blog/202011/25/b01f8ef37075517674b5808283db2e32.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)

由一个任务维护,并且用来计算某个结果的所有数据,都属于这个任务的状态
可以认为状态就是一个本地变量,可以被任务的业务逻辑访问
Flink会进行状态管理,包括状态一致性、故障处理以及高效存储和访问,以便开发人员可以专注于应用程序的逻辑

Flink的状态
在Flink中,状态始终与特定算子相关联
为了使运行时的Flink了解算子的状态,算子需要预先注册其状态
总的来说,有两种类型的状态:
算子状态(Operator State)
算子状态的作用范围限定为算子任务
键控状态(KeydState)
根据输入数据流中定义的键(key)来维护和访问

算子状态(Operator State)

算子状态的作用范围限定为算子任务,由同一并行任务所处理的所有数据都可以访问到相同的状态

状态对于同一子任务而言是共享的

算子状态不能由相同或不同算子的另一个子任务访问

算子状态数据结构

列表状态(List state)
将状态表示为一组数据的列表
联合列表状态(Union List State)
也将状态表示为数据的列表。它与常规列表状态的区别在于,在发生故障时,或者从保存点(savepoint)启动应用程序时如何恢复
广播状态(Broadcast state)
如果一个算子有多项任务,而它的每项任务状态又都相同,那么这种特殊情况最适合应用广播状态。

键控状态(Keyed State)

Flink从入门到真香(15、Flink状态管理)

键控状态是根据输入数据流中定义的键(key)来维护和访问的
Flink为每个key维护一个状态实例,并将具有相同键的所有数据,都分区到同一个算子任务中,这个任务会维护和处理这个key对应的状态
当任务处理一条数据时,它会自动将状态的访问范围限定为当前数据的key

键控状态的数据结构

值状态(Value state):将状态表示为单个的值
列表状态(List state):将状态表示为一组数据的列表
映射状态(Map state): 将状态表示为一组Key-Value对
聚合状态(Reducing state & Aggergating State): 将状态表示为一个用于聚合操作的列表


# 上代码举个栗子 
## 对于温度传感器的温度值跳变(下一个值跟上一个值的差)超过10度,就报警

package com.mafei.apitest

import com.mafei.sinktest.SensorReadingTest5
import org.apache.flink.api.common.functions.RichFlatMapFunction
import org.apache.flink.api.common.state.{ValueState, ValueStateDescriptor}
import org.apache.flink.streaming.api.scala.{OutputTag, StreamExecutionEnvironment, createTypeInformation}
import org.apache.flink.util.Collector

object StateTest {
def main(args: Array[String]): Unit = {
//创建执行环境
val env = StreamExecutionEnvironment.getExecutionEnvironment

env.getConfig.setAutoWatermarkInterval(200) //直接全局设置watermark的时间为200毫秒
val inputStream = env.readTextFile("/opt/java2020_study/maven/flink1/src/main/resources/sensor.txt")

env.setParallelism(1)

//先转换成样例类类型
val dataStream = inputStream
  .map(data => {
    val arr = data.split(",") //按照,分割数据,获取结果
    SensorReadingTest5(arr(0), arr(1).toLong, arr(2).toDouble) //生成一个传感器类的数据,参数中传toLong和toDouble是因为默认分割后是字符串类别
  })

//需求是:  对于温度传感器的温度值跳变(下一个值跟上一个值的差)超过10度,就报警

val alertStream = dataStream
    .keyBy(_.id) //根据sensor的id进行聚合,因为要去每个sensor独立的温度变化,不能串了
    // 这是第一种方式,自定义类

// .flatMap( new TempChangeAlertFunction(10.0)) //定义一个flatmap,传入一个自定义的实现类,超过10度就报警,参数传进去

    //这是第二种方法,用flatMapWithState
    .flatMapWithState[(String,Double,Double), Double]({

      case (data: SensorReadingTest5, None)=> (List.empty, Some(data.temperature))
      case(data: SensorReadingTest5,lastTemp: Some[Double])=> {
        //跟最新的温度值做差值比较
        val diff = (data.temperature - lastTemp.get).abs
        if(diff > 10.0)(
          List((data.id, lastTemp.get, data.temperature)),Some(data.temperature)
        )else

          (List.empty, Some(data.temperature))
      }
    })
alertStream.print()

// dataStream.print()
env.execute("state test。。。。。")
}
}

//实现自定义RichFlatMapFunction
class TempChangeAlertFunction(tempThreshould: Double) extends RichFlatMapFunction[SensorReadingTest5,(String,Double, Double)]{
//定义状态保存上一次的温度值
lazy val lastTempState: ValueState[Double] = getRuntimeContext.getState(new ValueStateDescriptor[Double]("last-temperature", classOf[Double]))

override def flatMap(in: SensorReadingTest5, collector: Collector[(String, Double, Double)]): Unit = {

//先获取上一次的温度值数据
val lastTemper = lastTempState.value()
//把当前温度值更新为lastTempState
lastTempState.update(in.temperature)
//跟最新的温度值求差值做比较
val tempDiff = (in.temperature - lastTemper).abs
println("collect....................这一次的值: "+in.temperature+"...............上一次的值: "+lastTemper)

// println("来数据了。。。。。。。。。。。。。。。。。。。。。")
if(tempDiff > tempThreshould){
collector.collect((in.id, lastTemper, in.temperature))
}
Thread.sleep(1000)
}
}


源文件sensor.txt数据内容

sensor1,1603766281,1
sensor2,1603766282,42
sensor3,1603766283,43
sensor4,1603766240,40.1
sensor4,1603766284,20
sensor4,1603766249,40.2

猜你喜欢

转载自blog.51cto.com/mapengfei/2554666