Spark-转换执行的随机顺序问题

时间:2019-03-22 16:37:51

标签: scala apache-spark

Spark转换的执行顺序似乎是任意的。

我们有2个RDD,其中包含我们分类的相关事件。多个分类器应用于rdd1,但是为了简洁起见,我仅描述发生问题的部分。

伪代码类似于:

total_count = rdd1.size
// filter1
(organics, duplicates) = Deduplicate rdd1 events (classify events as organic and duplicates)
duplicates.persist(DISK_ONLY)
rdd1 = organics
if (specific_client) {
  // filter2
  Load rdd2 Events
  Join rdd1 and rdd2
  (organics, invalid) = Classify rdd1 events according to joined information from rdd2
  invalid.persist(DISK_ONLY)
}
Check total_count == size(organics + invalid + duplicates) // here it fails

我们遇到的问题是,在某些运行中,通过大小检查会通过,而在某些情况下会失败。查看执行时间表,我们注意到在filter2 之后执行filter1时,它失败。并且当失败时,右手的大小总是大于初始total_count

当代码指示filter1的输出是filter2的输入时,为什么Spark会在filter2之后安排filter1的执行?

在filter2之后执行filter1时,为什么所有零件的计数返回的元素数都比装入的要多? (我怀疑是加入通话)

奇怪的是,当我们在单个节点上本地运行代码时,它从未失败。当我们通过Spark shell连接到AWS EMR时,它从未失败。仅当在具有4个工作节点的AWS EMR集群上作为常规Spark作业运行时,该操作才会失败。

论坛建议我们应该以某种方式强制Spark在filter2之前计算filter1。以下操作无效:

  • 在filter1之后调用organics.persist(MEMORY_ONLY | DISK_ONLY)
  • 在filter1之后调用organics.cache()
  • 在filter1之后调用organics.count()
  • 在filter1之后调用organics.checkpoint()
  • 在filter2的末尾调用organics.persist(DISK_ONLY)

其工作方式是在filter1之后调用organics.persist(DISK_ONLY),然后调用organics.count。但是,我们不确定这是否是最佳解决方案,因为它看起来很暴力并且会导致数据混排。

所以总结一下。

  1. 当代码指示filter1的输出是filter2的输入时,为什么Spark会在filter2之后安排filter1的执行?
  2. 为什么以相反的顺序执行时,它返回的元素多于加载的元素?
  3. persist + count是执行转换顺序的最佳解决方案吗?

0 个答案:

没有答案