Spark Streaming的mapWithState的状态范围是什么?

时间:2018-07-13 08:52:54

标签: scala apache-spark spark-streaming

通过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个状态(每个键一个)?

1 个答案:

答案 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

并且您需要确保foobar一起处理,而quuxbletch被处理,您需要执行以下操作:

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
}