flink之State
state概述
- state一般指一个具体的task/operator的状态,state数据默认保存在java的堆内存中。
- flink通过state和checkpoint更容易实现At -least-once 和 Exactly-once
state流程
state类型
flink有两种基本类型的state
- operator state
- keyed state
每种类型的state都可以以两种形式存在
- 原生状态(raw state)
- 由算子自己管理数据结构,当触发checkpoint操作过程中,flink并不知道数据内部的数据结构,只是将数据转换成bytes数据存储在checkpoint中,当checkpoint恢复任务时,算子自己再反序列化出状态的数据结构
- 托管状态(managed state)
- 由Flink Runtime控制和管理状态数据,并将状态数据转换成为内存的Hash tables或 RocksDB的对象存储,然后将这些数据通过内部的接口持久化到checkpoints中,任务异常时可以通过这些状态数据恢复任务。
- 推荐使用ManagedState管理状态数据,ManagedState更好的支持状态数据的重平衡以及更加完善的内存管理
Managed State | Raw State | |
---|---|---|
状态管理方式 | Flink Runtime托管,自动存储、自动恢复、自动伸缩 | 用户自己管理 |
状态数据结构 | Flink提供的常用数据结构,如ListState、MapState等 | 字节数组:byte[] |
使用场景 | 绝大多数Flink算子 | 用户自定义算子 |
operator state
- operator state是task级别的state,每个task对应一个state
- Kafka Connector source中的每个分区(task)都需要记录消费的topic的partition和offset等信息
- operator state 只有一种托管状态:ValueState (见下面的key state)
示例
结合listState实现每两条数据进行输出打印一次,不用区分数据的key
import org.apache.flink.streaming.api.functions.sink.SinkFunction
import org.apache.flink.streaming.api.scala.{
DataStream, StreamExecutionEnvironment}
import scala.collection.mutable.ListBuffer
/**
* 实现每两条数据进行输出打印一次,不用区分数据的key
*/
object OperatorListState {
def main(args: Array[String]): Unit = {
val env = StreamExecutionEnvironment.getExecutionEnvironment
import org.apache.flink.api.scala._
val sourceStream: DataStream[(String, Int)] = env.fromCollection(List(
("spark", 3),
("hadoop", 5),
("hive", 7),
("flume", 9)
))
sourceStream.addSink(new OperateTaskState).setParallelism(1)
env.execute()
}
}
class OperateTaskState extends SinkFunction[(String,Int)]{
//定义一个list 用于我们每两条数据打印一下
private var listBuffer:ListBuffer[(String,Int)] = new ListBuffer[(String, Int)]
override def invoke(value: (String, Int), context: SinkFunction.Context[_]): Unit = {
listBuffer.+=(value)
if(listBuffer.size ==2){
println(listBuffer)
//清空state状态
listBuffer.clear()
}
}
}
输出
key state
- keyed state是基于keyedStream上的状态,这个状态是跟特定的key绑定
- keyedStream流上的每一个key,都对应一个state
flink针对keyed state提供了一下可以保存state的数据结构
keyed state托管状态有六种类型:
- ValueState
- ListState(常用)
- MapState(常用 )
- ReducingState
- FoldingState
- AggregatingState
ValueState
将相同key的数据进行聚合
示例
使用ValueState实现求平均值
import org.apache.flink.api.common.functions.RichFlatMapFunction
import org.apache.flink.api.common.state.{
ValueState, ValueStateDescriptor}
import org.apache.flink.configuration.Configuration
import org.apache.flink.streaming.api.scala.StreamExecutionEnvironment
import org.apache.flink.util.Collector
object valueState {
def main(args: Array[String]): Unit = {
val env: StreamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment
import org.apache.flink.api.scala._
env.fromCollection(List((1L,3d),(1L,4d),(1L,5d),(1L,6d),(1L,7d)))
.keyBy(_._1)
.flatMap(new CountWindowsAve)
.print()
env.execute()