我试图从概念上理解MapState的行为,官方文档似乎与我在部署中看到的行为相冲突。
在keyyed流中,我期望具有MapState的函数对于它正在处理的元素的每个流键具有不同的内容。但是,我看到的是跨整个密钥组共享的单个Map,例如整个worker。
我需要帮助协调我们所看到的行为与文档断言MapState的工作方式。
例如我们有一个带有MapState初始化的KeyedProcessFunction:
@Transient
var cumulativeSpendMap: MapState<Int, Long>? = null // Key int is the day of the month
override fun open(parameters: Configuration?) {
val mapStateDescriptor = MapStateDescriptor(
"ProcessSomeEvent.cumulativeSpend",
BasicTypeInfo.INT_TYPE_INFO,
BasicTypeInfo.LONG_TYPE_INFO
)
cumulativeSpendMap = runtimeContext.getMapState(mapStateDescriptor)
}
医生说:
键由系统自动提供,因此函数总是看到映射到当前元素的键的值
,但在我的实验中,Map在单个worker上的所有密钥之间共享,这意味着它属于整个KeyGroup。不同的流键可以自由地覆盖彼此的值。
这是否意味着在给定的TaskManager实例上处理的所有元素之间共享一个映射,而不管元素的键是什么?
更具体地说,我需要显式地包括流键作为存储在Map中的值的键的一部分吗?
我误解了什么?
不幸的是,在这里很容易迷失在术语中。希望我能说清楚。
Flink提供了三种类型的键控状态(有时称为键分区状态):
ValueState
ListState
MapState
这些都在键值存储中维护状态,该存储由正在处理的KeyedStream
的键索引。换句话说,
ValueState
是键到值的映射ListState
是键到列表的映射MapState
是键到地图的映射
在每种情况下,外部映射都是一个分布式的分片映射,每个任务槽管理分配给该槽的键组的分片。在MapState
的情况下,键-值存储中的值本身就是映射(使用其他特定于应用程序的键集)。
在你的情况下,我相信ValueState
是你想要使用的。有关这方面的更多信息,包括一个示例,请参阅Flink文档中的教程。