为副作用运行Spark作业是否有意义?

时间:2015-10-28 16:40:33

标签: apache-spark

我想运行一个Spark作业,每个RDD负责通过网络连接发送某些流量。每个RDD的返回值不是很重要,但我或许可以要求它们返回发送的消息数。重要的部分是网络流量,这基本上是在每个RDD上运行功能的副作用。

在Spark中执行上述任务是个好主意吗?

我正在尝试模拟来自多个来源的网络流量,以测试接收端的数据收集基础架构。我可以手动设置多台机器来运行发送器,但我认为如果我可以利用Spark现有的分布式框架会很好。

然而,似乎Spark专为程序设计“计算”然后“返回”某些东西,而不是程序运行它们的副作用。我不确定这是不是一个好主意,并希望得到别人的意见。

要清楚,我正在考虑以下内容

IDs = sc.parallelize(range(0, n))

def f(x):
    for i in range(0,100):
        message = make_message(x, i)
        SEND_OVER_NETWORK(message)
    return (x, 100)

IDsOne = IDs.map(f)
counts = IDsOne.reduceByKey(add)

for (ID, count) in counts.collect():
    print ("%i ran %i times" % (ID, count))

1 个答案:

答案 0 :(得分:2)

一般来说,它没有意义:

  1. Spark是一个重量级框架。其核心是这种巨大的机器,可确保数据的正确分配,收集,恢复等等。它对整体性能和延迟有重大影响,但在仅有副作用的任务中不能提供任何好处
  2. Spark并发具有相对较低的粒度,分区是并发的主要单位。在这个级别,处理变得同步。在完成当前分区之前,您无法转到下一个分区。

    让我们说在你的情况下只有一个慢SEND_OVER_NETWORK。如果使用map,则几乎会阻止整个分区的处理。您可以使用mapPartitions进入较低级别,使SEND_OVER_NETWORK异步,并仅在处理完整个分区时返回。它更好但仍然不是最理想的。

    您可以增加分区数量,但这意味着更高的簿记费用,因此在一天结束时您可能会使情况变得更糟而不是更好。

  3. Spark API主要用于无副作用的操作。这使得难以表达不适合该模型的操作。

    可以说更重要的是Spark只保证每个操作至少执行一次(如果rdd从未实现,则忽略零次)。如果应用程序需要例如一次性语义,那么事情变得棘手,尤其是当您考虑第2点时。

    可以跟踪主Spark逻辑之外的每个分区的本地状态,但是如果你到达那里,那么Spark就不是正确的工具了。