通常使用Spark的流式框架如Spark Streaming,做无状态的流式计算是非常方便的,仅需处理每个批次时间间隔内的数据即可,不需要关注之前的数据,这是建立在业务需求对批次之间的数据没有联系的基础之上的。
但如果我们要跨批次做一些数据统计,比如batch是3秒,但要统计每1分钟的用户行为,那么就要在整个流式链条中维护一个状态来保存近1分钟的用户行为。
那么如果维护这样一个状态呢?一般情况下,主要通过以下几种方式:
-
spark内置算子:updateStateByKey、mapWithState
-
第三方存储系统维护状态:如redis、alluxio、HBase
本篇主要以spark内置算子:updateStateByKey通过一些示例代码(不涉及offset管理),来看看如何进行状态维护。(下篇文章会介绍mapWithState)
updateStateByKey
分析相关源码发现,这个算子的核心思想就是将之前有状态的RDD和当前的RDD做一次cogroup,得到一个新的状态的RDD,具有如下特点:
- 可以设置初始状态
- key超时删除。用updatefunc返回None值。updateFunc不管是否有已保存状态key的新数据到来,都会被已存在状态的key调用,新增的key也会调用
- 不适合大数据量状态存储,尤其是key的维度比较高、value状态比较大的
object StateOperator {
private val brokers = "kafka-1: