我有一个执行典型ETL工作的spark 1.3应用程序:它从几个不同的hive表中读取,对数据帧执行连接和其他操作,最后将输出作为文本文件保存到HDFS位置。
这个应用程序工作正常,除了它的第6阶段经常遇到错误消息,如“失败而没有被确认”。 Spark将重试并最终成功完成所有阶段。
为了加快重试过程,我想缓存阶段6的父数据帧。我为阶段6中使用的数据帧添加了.persist(StorageLevel.MEMORY_AND_DISK_SER)
。但是,当作业运行时,来自火花UI,我可以看到没有任何缓存/持久化。当阶段6失败时,所有需要的数据都会重新计算。
这两个集群是相同的,一个是独立的,一个是在Yarn下。我还尝试了.cache()
或.persist(StorageLevel.MEMORY_ONLY)
等但结果相同。我不确定这是什么原因。我想缓存的数据与可用内存相比并不大(~50G vs~500G)。唯一值得一提的是我想要缓存的数据以后从未使用过多次 - 理论上,如果第6阶段没有经常失败,我根本不需要缓存。
任何人都有更多关于为什么持久/缓存行为如此的见解?
答案 0 :(得分:5)
您可能已在阶段边界缓存RDD,因此实际缓存和错误发生在同一阶段。尝试通过对每个RDD运行操作来强制实现RDD,例如:在你缓存它们之后立即.count()
。
另请注意,当执行程序死亡时,它缓存的数据随之而来。如果您的错误属于此类别,那么您可以更好地使用.checkpoint()
而不是缓存。
最后,我建议花时间了解实际导致您看到的错误的原因(听起来像超时太低),否则您将不断浪费重新计算数据并最终再次遇到类似情况。