通过Spark Streaming,我可以创建一个DStream[(K, V)]
,可以在其中使用mapWithState
在流处理过程中保持某些状态。 map
函数的设置如下:
val mapFun =
(key: K, maybeValue: Option[V], state: State[S]) => {
// Do stuff
}
然后我可以使用:
val mappedStreamWithState = stream.mapWithState(StateSpec.function(mapFun))
我现在的问题是:state
的范围是什么?是键还是分区?
比方说,流来自具有3个分区的Kafka主题,但可以有300个键。据我了解,流中的每个RDD
都有3个分区,每个分区约有100个键。那么会存在3个状态(每个分区一个)还是300个状态(每个键一个)?
答案 0 :(得分:0)
我正在回答自己的问题,因此如果另一个问题相同,我可以将其标记为已接受。
tl; dr::状态的范围是分区,并且依赖于键时会有更多警告。
我对mapWithState
进行了很多调查,这是我发现的结果:
mapWithState
仅适用于DStream[(A, B)]
。到目前为止一切顺利。mapWithState
生成的传入流被密钥隐式分区。根据到目前为止的发现,分区数取决于可用的工作程序任务数。例如,在具有8个线程的CPU上以local[*]
模式运行它会产生8个分区。Map[TKey, TStateForTheKey]
stream.repartition(1).mapWithState(...)
的事情是徒劳的因此,假设您在DStream[(String, Int)]
中有这样的数据:
foo,1
bar,8
foo,23
quux,423
bletch,42
bar,5
并且您需要确保foo
和bar
一起处理,而quux
和bletch
被处理,您需要执行以下操作:
stream.
flatMap {
case (k, v) if Seq("foo", "bar").contains(k) => Some("foobar" -> (k, v))
case (k, v) if Seq("quux", "bletch").contains(k) => Some("quuxbletch" -> (k, v))
case _ => None
}.
mapWithState(StateSpec.function(myFunc))
您的映射功能必须类似于:
val myFunc = (key: String, maybeRecord: Option[(String, Int)], state: State[Something]) => {
// Do something with the record
}