Managed Keyed State
Managed Keyed State接口提供不同类型的状态的访问,所有状态都限于当前输入元素的key。这意味着只能在KeyedStream上使用这种类型的状态。用户可以通过stream.keyBy(...)
创建,flink内建了以下六种的state。
-
ValueState<T>
:
使用场景:该状态主要用于存储单一状态值。
保留了一个可以更新和检索的值(如上所述,作用于输入元素的key的范围,因为运算看的每个key可能有一个值)。可以试用update(T)设置该值,并使用T value()检索该值。 -
ListState<T>
:
使用场景:该状态主要用于存储集合状态值。
保留的元素列表,可以追加元素并在所有当前存储的元素上检索Iterable。使用add(T)
或addAll(List<T>)
添加元素,可以试用Iterable<T> get()
检索Iterable。还可以使用update(List<T>)
重写现有的list。 -
MapState<UK, UV>
:
使用场景:该状态主要用于存储一个Map集合。
保留一个映射列表。可以将键值对放入状态,并在所有当前存储的映射上检索Iterable。使用put(UK, UV)
或putAll(Map<UK, UV>)
添加映射。可以试用get(UK)
检索与用户key关联的值。可以分别使用entries()
,keys()
和values()
来检索映射,键和值的可迭代视图。 -
ReducingState<T>
:
使用场景:该状态主要用于存储单一状态值。该状态会将添加的元素和历史状态自动做运算,调用用户提供的ReduceFunction。
保留一个值,表示添加到状态的所有值得聚合。该接口类似于ListState,不过是试用add(T)
添加的元素,reduced一个聚合是使用特定的ReduceFunction。 -
AggreatingState<IN, OUT>
:
使用场景:该状态主要用于存储单一状态值。该状态会将添加的元素和历史状态自动做元素,调用用户提供的AggregateFunction,该状态和ReducingState不同点在于数据输入和输出类型可以不一致。
保留一个值镖师添加到状态的所有值的聚合。与ReducingState相反,聚合类型可能与添加到状态的元素类型不同。接口与ListState相同,不过是试用add(T)
添加的元素,reduced一个聚合是使用特定的FoldFunction。 -
FoldingState<T, ACC>
:
使用场景:该状态主要用于存储单一状态值。该状态会将添加的元素和历史状态自动做运算,调用用户提供的FoldFunction,该状态和ReducingState不同点在于数据输入和中间结果类型可以不一致。
保留一个值表示添加到状态的所有值得还有个。与Reducing相反,聚合类型可能与添加到状态的元素类型不同。该接口类似于ListState,不过是试用add(T)
添加的元素,reduced一个聚合是使用特定的FoldFunction。
所有类型的状态都还有个clear()
方法,可以清除当前key的状态。
这些状态对象仅用于状态接口。状态不一定存储在内部,但可能驻留在磁盘或者其他地方。从状态中获取的值取决于输入元素的键。因此,如果设计的键不同,那么在一次用户函数调用中得到的值可能与在另一次调用得到的值不同。
要获取状态句柄,必须创建StateDescriptoy
。这保存了状态的名称(可以创建多个状态,并且它们必须具有唯一的名称以便于使用),状态所持有的值得类型,并且可能是用户指定的函数,例如ReduceFunction。根据要检索的状态类型,可以创建ValueStateDesctiptor
,ListStateDescriptor
,ReducingStateDescriptor
,FoldingStateDescriptor
或MapStateDescriptor
。
状态是使用RuntimeContext
来访问的,因此它只能在丰富的函数中使用。RichFunction
中可用RuntimeContext
有以下访问状态的访问。
ValueState getState(ValueStateDescriptor)
ReducingState getReducingState(ReducingStateDescriptor)
ListState getListState(ListStateDescriptor)
AggregatingState getAggregatingState(AggregatingStateDescriptor)
FoldingState getFoldingState(FoldingStateDescriptor)
MapState getMapState(MapStateDescriptor)
示例代码:
导入整合依赖:
<dependencies>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-streaming-scala_2.11</artifactId>
<version>1.8.2</version>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-connector-filesystem_2.11</artifactId>
<version>1.8.2</version>
</dependency>
</dependencies>
ValueState
object FlinkKeyedStateValueState {
def main(args: Array[String]): Unit = {
val env = StreamExecutionEnvironment.getExecutionEnvironment
env.socketTextStream("Flink", 9999)
.flatMap(line=>line.split("\\s+"))
.map(word=>(word,1))
.keyBy("_1")
.map(new ValueStateMapFunction)
.print("输出")
env.execute("FlinkKeyedStateValueState")
}
}
class ValueStateMapFunction extends RichMapFunction[(String,Int),(String,Int)]{
var valueState:ValueState[Int]=_
override def open(parameters: Configuration): Unit = {
val vsd = new ValueStateDescriptor[Int]("wordcount", createTypeInformation[Int])
val runtimeContext= getRuntimeContext
valueState=runtimeContext.getState(vsd)
}
override def map(value: (String, Int)): (String, Int) = {
//获取历史值
var historyCount = valueState.value()
//更新历史值
valueState.update(historyCount+value._2)
(value._1,valueState.value())
}
}
ReducingState
object FlinkKeyedStateReducingState {
def main(args: Array[String]): Unit = {
val env = StreamExecutionEnvironment.getExecutionEnvironment
env.socketTextStream("Flink", 9999)
.flatMap(line=>line.split("\\s+"))
.map(word=>(word,1))
.keyBy("_1")
.map(new ReducingStateMapFunction)
.print("输出")
env.execute("FlinkKeyedStateReducingState")
}
}
class ReducingStateMapFunction extends RichMapFunction[(String,Int),(String,Int)]{
var reducingSate:ReducingState[Int]=_
override def open(parameters: Configuration): Unit = {
val rsd = new ReducingStateDescriptor[Int]("wordcount",new ReduceFunction[Int] {
override def reduce(value1: Int, value2: Int): Int = value1+value2
},createTypeInformation[Int])
val runtimeContext= getRuntimeContext
reducingSate=runtimeContext.getReducingState(rsd)
}
override def map(value: (String, Int)): (String, Int) = {
reducingSate.add(value._2)
(value._1,reducingSate.get())
}
}
ListState
object FlinkKeyedStateListState {
def main(args: Array[String]): Unit = {
val env = StreamExecutionEnvironment.getExecutionEnvironment
//zhangsan 北京
env.socketTextStream("Flink", 9999)
.map(line=>line.split("\\s+"))
.map(ts => (ts(0),ts(1)))
.keyBy("_1")
.map(new ListStateMapFunction)
.print("输出")
env.execute("FlinkKeyedStateListState")
}
}
class ListStateMapFunction extends RichMapFunction[(String,String),(String,String)]{
var listState:ListState[String]=_
override def open(parameters: Configuration): Unit = {
val lsd = new ListStateDescriptor[String]("ListState",createTypeInformation[String])
val runtimeContext= getRuntimeContext
listState=runtimeContext.getListState(lsd)
}
override def map(value: (String, String)): (String, String) = {
var historyData = listState.get().asScala.toList
historyData = historyData.::(value._2).distinct
listState.update(historyData.asJava)
(value._1,historyData.mkString(","))
}
}
MapState
object FlinkKeyedStateMapState {
def main(args: Array[String]): Unit = {
val env = StreamExecutionEnvironment.getExecutionEnvironment
//zhangsan 电子类 100.0
env.socketTextStream("Flink", 9999)
.map(line=>line.split("\\s+"))
.map(ts => (ts(0),ts(1),ts(2).toDouble))
.keyBy("_1")
.map(new MapStateMapFunction)
.print("输出")
env.execute("FlinkKeyedStateMapState")
}
}
class MapStateMapFunction extends RichMapFunction[(String,String,Double),(String,String)]{
var mapState:MapState[String,Double]=_ //记录每一类目消费
var reduceState:ReducingState[Double]=_ //记录总消费
override def open(parameters: Configuration): Unit = {
val msd = new MapStateDescriptor[String, Double]("MapState", createTypeInformation[String], createTypeInformation[Double])
val rsd= new ReducingStateDescriptor[Double]("ReducingState",new ReduceFunction[Double] {
override def reduce(value1: Double, value2: Double): Double = value1+value2
},createTypeInformation[Double])
mapState=getRuntimeContext.getMapState(msd)
reduceState=getRuntimeContext.getReducingState(rsd)
}
override def map(value: (String, String, Double)): (String, String) = {
reduceState.add(value._3)
var cost=0.0
if(mapState.contains(value._2)){
cost=mapState.get(value._2)
}
mapState.put(value._2,cost+value._3)
var total=reduceState.get() + "\t"+mapState.entries().iterator().asScala.toList.map(t=> t.getKey+":"+t.getValue).mkString(",")
(value._1,total)
}
}
FoldSate
object FlinkKeyedStateFoldState {
def main(args: Array[String]): Unit = {
val env = StreamExecutionEnvironment.getExecutionEnvironment
//zhangsan 电子类 100.0
env.socketTextStream("Spark", 9999)
.map(line=>line.split("\\s+"))
.map(ts => (ts(0),ts(1),ts(2).toDouble))
.keyBy(t=>t._1+":"+t._2)
.map(new FoldStateMapFunction)
.print("输出")
env.execute("FlinkKeyedStateFoldState")
}
}
class FoldStateMapFunction extends RichMapFunction[(String,String,Double),(String,String)]{
var foldState:FoldingState[Double,Double]=_ //仅仅只可以计算和
var reduceState:ReducingState[Int]=_ //计数
override def open(parameters: Configuration): Unit = {
//添加值类型 累加器类型`
val fsd = new FoldingStateDescriptor[Double,Double]("FoldingState",0.0,
new FoldFunction[Double,Double]{
override def fold(accumulator: Double, value: Double): Double = accumulator+value
},createTypeInformation[Double])
val rsd = new ReducingStateDescriptor[Int]("ReducingState",new ReduceFunction[Int] {
override def reduce(value1: Int, value2: Int): Int = value1+value2
},createTypeInformation[Int])
foldState=getRuntimeContext.getFoldingState(fsd)
reduceState=getRuntimeContext.getReducingState(rsd)
}
override def map(value: (String,String,Double)): (String, String) = {
reduceState.add(1)
foldState.add(value._3)
(value._1,value._2+"\t"+(foldState.get()/reduceState.get()))
}
}
AggregatingState
object FlinkKeyedSateAggregatingState {
def main(args: Array[String]): Unit = {
val env = StreamExecutionEnvironment.getExecutionEnvironment
//zhangsan 电子类 100.0
env.socketTextStream("Flink", 9999)
.map(line=>line.split("\\s+"))
.map(ts => (ts(0),ts(1),ts(2).toDouble))
.keyBy(t=>t._1+":"+t._2)
.map(new AggregatingStateMapFunction)
.print("输出")
env.execute("FlinkKeyedStateFoldState")
}
}
class AggregatingStateMapFunction extends RichMapFunction[(String,String,Double),(String,String)]{
var aggregatingState:AggregatingState[Double,Double]=_
override def open(parameters: Configuration): Unit = {
//添加值类型 累加器类型
val asd = new AggregatingStateDescriptor[Double,(Double,Int),Double]("AggregatingState",
new AggregateFunction[Double,(Double,Int),Double] {
//创建初始值
override def createAccumulator(): (Double, Int) = (0.0,0)
//局部计算
override def add(value: Double, accumulator: (Double, Int)): (Double, Int) = {
(accumulator._1+value, accumulator._2+1)
}
//合并局部结果
override def merge(a: (Double, Int), b: (Double, Int)): (Double, Int) = {
(a._1+b._1,a._2+b._2)
}
//获取最终结果
override def getResult(accumulator: (Double, Int)): Double = accumulator._1/accumulator._2
}
,createTypeInformation[(Double,Int)])
aggregatingState = getRuntimeContext.getAggregatingState(asd)
}
override def map(value: (String,String,Double)): (String, String) = {
aggregatingState.add(value._3)
(value._1,value._2+"\t"+aggregatingState.get())
}
}