我在下面有这个flink程序:
object WindowedWordCount {
class MyCoMap extends RichCoMapFunction[String, String, String] {
private var usersMap: MapState[String, String] = _
override def open(parameters: Configuration): Unit = {
usersMap = getRuntimeContext.getState(
//Error here
new MapStateDescriptor[String, String]("usersMap", TypeInformation[String], TypeInformation[String)
)}
override def map1(value: String): String = {
//Grab userId and timeStampOfUserId here
usersMap.put(userId,timeStampOfUserId)
println(usersMap)
"Adding user from event stream to global map: " + timeStampOfUserId
}
override def map2(value: String): String = {
//Do something with the second stream
}
}
}
我在上面的代码中遇到的问题是,当我向全局定义的map1
添加MyCoMap
时,在key-value
类内的users HashMap
函数中,我添加key-value
每个key-value
的一些原因,它覆盖了之前的值。所以我的地图总是包含1 users.put("user1", "abc")
...
例如,如果它添加{"user1"="abc"}
,则地图将包含key-value
,然后将另一个users.put("user2", "abc")
{"test2"="abc"}
地图设为{"test1"="abc", "test2"="abc"}
而不是MapState
}。
修改
是的,我想加入userId。 Stream1以每秒1条消息进入,而stream2以每6秒1条消息进入。我想将stream1中的userId添加到map1
(在map2
函数中),然后在userID
函数中我想检查来自stream2的MapSate
是否存在在MapState
。
我对这个领域缺乏了解,但是当你说键控状态时,我假设所有相同的键将在同一节点上处理正确并且每个节点都获得它自己的MapState
对象?由于我主要担心的是当我从stream2加入userId时,我想确保收集来自stream1的所有userId,并且当map2函数中出现{{1}}时,它们位于同一节点上。 / p>
答案 0 :(得分:4)
如果我的要求正确,您希望在user
上加入两个流。
这可以通过在user
字段上键入两个流来完成:
val stream1: DataStream[(String, String)] = ??? // first field is user
val stream2: DataStream[(String, String)] = ??? // first field is user
val connected: DataStream[X] = stream1
.connect(stream2) // connect both streams
.keyBy(_._1, _._1) // key both streams on first field
.map(new YourCoMapFunction())
CoMapFunction
应该使用Keyed State,即与您keyBy
处于同一属性上的状态(您的情况下是用户)。因此,键控状态本质上是分片的,分布式的HashMap
。请注意,键控状态只能在本地访问。与州合作时,您必须确保删除所有不再需要的状态。否则,你的州在某些时候可能会变得太大。