从官方文档我们可以看到:
对于仅在操作内执行的累加器更新,Spark 保证每个任务对累加器的更新只会是 应用一次,即重新启动的任务不会更新该值。在 转换时,用户应该知道每个任务的更新可能 如果重新执行任务或工作阶段,则应用多次。
我认为这意味着累加器只应在动作内执行,例如rdd.foreachPartition()
通过pyspark中的rdd.foreachPartition
API代码,我发现rdd.foreachPartition(accum_func)
等于:
rdd.mapPartitions(accum_func).mapPartitions(lambda i: [sum(1 for _ in i)]).mapPartitions(lambda x: [sum(x)]).mapPartitions(some_add_func).collect()
似乎 accum_func 可以在转换(rdd.mapPartition)中运行?
非常感谢任何解释
答案 0 :(得分:0)
如果运行map()操作分区的节点崩溃, Spark会在另一个节点上重新运行它,即使该节点没有崩溃,也只是简单 比其他节点慢得多,Spark可以抢先推出“推测”副本 另一个节点上的任务,如果完成则取结果。
即使没有节点发生故障,Spark也可能不得不重新运行任务来重建一个内存不足的缓存值。因此,最终结果是相同的函数可能会在同一数据上运行多次,具体取决于群集。
动作中使用的累加器,Spark仅将每个任务的更新应用于每个累加器一次。因此,如果我们想要一个可靠的绝对值计数器,无论是失败还是多次评估,我们都必须把它放在像foreach()这样的动作中。