Apache spark groupBy上的Pypark应用程序失败

Apache spark groupBy上的Pypark应用程序失败,apache-spark,pyspark,google-cloud-dataproc,Apache Spark,Pyspark,Google Cloud Dataproc,我正在尝试在Thread模式下运行作业,该模式处理从google云存储读取的大量数据(2TB) 管道可以总结如下: sc.textFile("gs://path/*.json")\ .map(lambda row: json.loads(row))\ .map(toKvPair)\ .groupByKey().take(10) [...] later processing on collections and output to GCS. This computation over th

我正在尝试在Thread模式下运行作业,该模式处理从google云存储读取的大量数据(2TB

管道可以总结如下:

sc.textFile("gs://path/*.json")\
.map(lambda row: json.loads(row))\
.map(toKvPair)\
.groupByKey().take(10)

 [...] later processing on collections and output to GCS.
  This computation over the elements of collections is not associative,
  each element is sorted in it's keyspace.
10GB的数据上运行时,完成时不会出现任何问题。 但是,当我在完整数据集上运行它时,它总是失败,因为容器中有以下日志:

15/11/04 16:08:07 WARN org.apache.spark.scheduler.cluster.YarnSchedulerBackend$YarnSchedulerEndpoint: ApplicationMaster has disassociated: xxxxxxxxxxx
15/11/04 16:08:07 ERROR org.apache.spark.scheduler.cluster.YarnClientSchedulerBackend: Yarn application has already exited with state FINISHED!
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/spark/python/pyspark/rdd.py", line 1299, in take
    res = self.context.runJob(self, takeUpToNumLeft, p)
  File "/usr/lib/spark/python/pyspark/context.py", line 916, in runJob
15/11/04 16:08:07 WARN org.apache.spark.ExecutorAllocationManager: No stages are running, but numRunningTasks != 0
    port = self._jvm.PythonRDD.runJob(self._jsc.sc(), mappedRDD._jrdd, partitions)
  File "/usr/lib/spark/python/lib/py4j-0.8.2.1-src.zip/py4j/java_gateway.py", line 538, in __call__
  File "/usr/lib/spark/python/pyspark/sql/utils.py", line 36, in deco
    return f(*a, **kw)
  File "/usr/lib/spark/python/lib/py4j-0.8.2.1-src.zip/py4j/protocol.py", line 300, in get_return_value
py4j.protocol.Py4JJavaError: An error occurred while calling z:org.apache.spark.api.python.PythonRDD.runJob.
: org.apache.spark.SparkException: Job cancelled because SparkContext was shut down
15/11/04 16:08:07警告org.apache.spark.scheduler.cluster.YarnSchedulerBackend$YarnSchedulerEndpoint:ApplicationMaster已解除关联:xxxxxxxxxx
15/11/04 16:08:07错误org.apache.spark.scheduler.cluster.YarnClientSchedulerBackend:纱线应用程序已退出,状态已完成!
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“/usr/lib/spark/python/pyspark/rdd.py”,第1299行,在take中
res=self.context.runJob(self,takeUpToNumLeft,p)
文件“/usr/lib/spark/python/pyspark/context.py”,第916行,在runJob中
15/11/04 16:08:07警告org.apache.spark.ExecutionAllocationManager:没有运行任何阶段,但numRunningTasks!=0
port=self.\u jvm.PythonRDD.runJob(self.\u jsc.sc(),mappeddd.\u jrdd,分区)
文件“/usr/lib/spark/python/lib/py4j-0.8.2.1-src.zip/py4j/java_gateway.py”,第538行,在调用中__
文件“/usr/lib/spark/python/pyspark/sql/utils.py”,第36行,deco格式
返回f(*a,**kw)
文件“/usr/lib/spark/python/lib/py4j-0.8.2.1-src.zip/py4j/protocol.py”,第300行,在get_return_值中
py4j.protocol.Py4JJavaError:调用z:org.apache.spark.api.python.PythonRDD.runJob时出错。
:org.apache.spark.SparkException:作业已取消,因为SparkContext已关闭
我试着通过连接到主机来逐个启动每个操作进行调查,但在groupBy上似乎失败了。我还试图通过添加节点、升级它们的内存和CPU数量来重新缩放集群,但仍然存在同样的问题

120个节点+1个具有相同规格的主节点: 8个vCPU-52GB内存

我试图找到有类似问题的线程,但没有成功,所以我不知道应该提供什么信息,因为日志不是很清楚,所以请随意询问更多信息

主键是每个记录所需的值,我们需要所有不带过滤器的键,大约代表600k个键。
是否真的有可能在不将集群扩展到大型集群的情况下执行此操作?我刚刚读到databricks对100TB的数据进行了排序(),这也涉及到大规模的洗牌。他们成功地将多个内存缓冲区替换为单个缓冲区,从而产生大量磁盘IO?“我的群集规模”是否可以执行此类操作?

总结一下我们通过对原始问题的评论所学到的知识,如果一个小数据集可以工作(特别是一个可能适合单个计算机总内存的数据集),然后一个大数据集尽管向群集添加了大量节点,但仍然失败,结合使用任何
groupByKey
,最常见的问题是您的数据中每个键的记录数是否存在显著的不平衡

特别是,
groupByKey
到目前为止仍然有一个限制,即一个键的所有值不仅必须被洗牌到同一台机器上,还必须能够放入内存中:

在a中有一些观点,其中包括一些关于变通方法的讨论;也就是说,您可以显式地将值/记录的散列字符串附加到键中,散列到一些小的bucket集合中,以便手动分割出大的组

在您的例子中,您甚至可以先执行
.map
变换,该变换只会有条件地调整已知热键的键,将其划分为子组,而不改变非热键


通常,“内存中”约束意味着您无法通过添加更多节点来绕过明显扭曲的关键点,因为它需要在热节点上“就地”缩放。对于特定情况,您可以将
spark.executor.memory
设置为
--conf
或在dataproc
gcloud beta dataproc jobs submit spark[other flags]--properties spark.executor.memory=30g
,只要max key的值都能适应30g(还有一些净空/开销)。但这将在任何可用的最大机器上实现,因此,如果当整个数据集增长时,最大密钥的大小可能会增加,那么最好更改密钥分布本身,而不是尝试启动单个执行器内存。

您能分享有关toKvPair功能的更多详细信息吗?分组时,每个键大约需要多少个值?它是否会为某些可能没有预期键的记录生成“null”键?当然,我只是编辑以添加更多信息。因此,问题的根源可能是groupByKey引入了不可扩展的每键瓶颈,而不是遇到“总数据集大小”约束。在petasort基准测试中,通常键本身仍然是唯一的,或者仅限于很少的重复项,而不管数据集的总体大小如何,这使得可以使用更大的集群进行扩展。请参阅Databricks的这篇文章,了解“热键”如何可能是一个陷阱。现在,如果2TB完全均匀地分布在600k密钥中,这应该不会是一个问题,并且应该可以找到您遇到的其他瓶颈,因为每个组只有3MB。问题是,若您有任何扭曲的非常流行的密钥,那个么您需要4GB之类的数据全部进入一个密钥。然后groupByKey将遇到问题。您是否可以尝试使用而不是groupByKey,然后对它们进行排序并获得最大计数?计数应该是可行的,即使你有歪斜的键,因为它应该能够结合总和增量从来没有加载到内存中的一个键的所有值。非常感谢你的详细答案!我分手了
/**
 * Group the values for each key in the RDD into a single sequence. Allows controlling the
 * partitioning of the resulting key-value pair RDD by passing a Partitioner.
 * The ordering of elements within each group is not guaranteed, and may even differ
 * each time the resulting RDD is evaluated.
 *
 * Note: This operation may be very expensive. If you are grouping in order to perform an
 * aggregation (such as a sum or average) over each key, using [[PairRDDFunctions.aggregateByKey]]
 * or [[PairRDDFunctions.reduceByKey]] will provide much better performance.
 *
 * Note: As currently implemented, groupByKey must be able to hold all the key-value pairs for any
 * key in memory. If a key has too many values, it can result in an [[OutOfMemoryError]].
 */