Flink Streaming keyedState的理解和使用

前言:

        本文所有理解、资料、图片基本上都是来源于官网,更多的是对官网描述的一个总结和概括。

下图是网上找到的一个应景图片。

 

一、什么是state

        State直译上去是”状态”一次,这个有点抽象难以理解。那什么是状态,究竟如何应用到我们的编码过程当中呢?在流式编程中,基本的处理流程是来一条数据,我就处理一条,这种单条和单条数据之间的处理很难形成一个对数据的分析,以下面的Access日志为例,我们对类似于这样的流式数据求一个实时访问量需求。

Access
IP地址服务商页面地址
10.x.x.xISPaddress

        如果没有state的时候,我们是怎么处理呢?每来一条数据就增加一个1,这个1可以保存在外部存储里,但是这个访问辆是很多的,如果每个流式任务都这样写,那外部存储肯定是受不住的。

          State呢这时候可以派出用场,可以把state看作是Flink在计算过程中提供的一个存储数据的盒子,让你把需要用到的数据暂放在这个盒子里面,你用的时候再去盒子里面取,不需要每次都要针对一个存储的状态开一个新的链接去外部访问。

        当然Flink自身也使用了State用来来容错处理,这个暂时不表。

二、KeyedState是什么

        上文提到了state是什么,简单的说就是Flink提供放东西的一个小盒子。那么在FlinkStreaming中,Flink提供了keyed Stata。首先简单介绍一下什么是keyedState,简单的说就是一个stream,使用keyby后变成keyedStream。

        那么在Flink当中有4种keyed state:

  • ValueState<T>: 可以存储任意类型的值,仅可以存储一个对象实例。

  • ListState<T>: 可以存储一个任意类型的队列,可以以List的方式存储多个。当然这里Value里面也可以放list.

  • ReducingState<T>: 仅可以存储一个值,需要增加一个对应的reduceFunction

  • AggregatingState<IN, OUT>: 与上面类似,就是输出值可以是其他类型

  • MapState<UK, UV>: 可以存储一个Map

2.1 正确使用方法

       对state来说,正确使用的前提就是了解state的值是和key绑定的,就是一个key对应的一个值。下面这段代码是我从官网找到的一个使用state进行数据两两求平均值的代码

class CountWindowAverage extends RichFlatMapFunction[(Long, Long), (Long, Long)] {

  private var sum: ValueState[(Long, Long)] = _

  override def flatMap(input: (Long, Long), out: Collector[(Long, Long)]): Unit = {

    // access the state value
    val tmpCurrentSum = sum.value

    // If it hasn't been used before, it will be null
    val currentSum = if (tmpCurrentSum != null) {
      tmpCurrentSum
    } else {
      (0L, 0L)
    }

    // update the count
    val newSum = (currentSum._1 + 1, currentSum._2 + input._2)

    // update the state
    sum.update(newSum)

    // if the count reaches 2, emit the average and clear the state
    if (newSum._1 >= 2) {
      out.collect((input._1, newSum._2 / newSum._1))
      sum.clear()
    }
  }

  override def open(parameters: Configuration): Unit = {
    sum = getRuntimeContext.getState(
      new ValueStateDescriptor[(Long, Long)]("average", createTypeInformation[(Long, Long)])
    )
  }
}


object ExampleCountWindowAverage extends App {
  val env = StreamExecutionEnvironment.getExecutionEnvironment

  env.fromCollection(List(
    (1L, 3L),
    (1L, 5L),
    (1L, 7L),
    (1L, 4L),
    (1L, 2L)
  )).keyBy(_._1)
    .flatMap(new CountWindowAverage())
    .print()
  // the printed output will be (1,4) and (1,5)

  env.execute("ExampleManagedState")
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

大锤爱编程

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

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

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

打赏作者

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

抵扣说明:

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

余额充值