Scala 火花任务挂起在[GC(分配失败)]
编辑:注意:执行器通常会发出消息[GC分配失败]。它运行它是因为它试图将内存分配给执行器,但执行器已满,因此在向执行器加载新内容时,它将尝试释放空间。如果您的执行器在循环中执行此操作,则可能意味着您试图加载到该执行器中的内容太大 我正在AWS EMR 5.8.0上运行Spark 2.2和Scala 2.11 我正在尝试对拒绝完成的数据集运行计数操作。令人沮丧的是,它只挂在一个特定的文件上。我在与S3不同的文件上运行此作业,没有问题-它完全完成。原始CSV文件本身是@18GB,我们对其进行转换,将原始CSV转换为结构列,并为其提供一个额外的列 我的环境的核心从机是8个实例,其中每个实例是:Scala 火花任务挂起在[GC(分配失败)],scala,amazon-web-services,apache-spark,amazon-emr,Scala,Amazon Web Services,Apache Spark,Amazon Emr,编辑:注意:执行器通常会发出消息[GC分配失败]。它运行它是因为它试图将内存分配给执行器,但执行器已满,因此在向执行器加载新内容时,它将尝试释放空间。如果您的执行器在循环中执行此操作,则可能意味着您试图加载到该执行器中的内容太大 我正在AWS EMR 5.8.0上运行Spark 2.2和Scala 2.11 我正在尝试对拒绝完成的数据集运行计数操作。令人沮丧的是,它只挂在一个特定的文件上。我在与S3不同的文件上运行此作业,没有问题-它完全完成。原始CSV文件本身是@18GB,我们对其进行转换,将
r3.2xlarge
16 vCore, 61 GiB memory, 160 SSD GB storage
我的Spark会话设置为:
implicit val spark = SparkSession
.builder()
.appName("MyApp")
.master("yarn")
.config("spark.speculation","false")
.config("hive.metastore.uris", s"thrift://$hadoopIP:9083")
.config("hive.exec.dynamic.partition", "true")
.config("hive.exec.dynamic.partition.mode", "nonstrict")
.config("mapreduce.fileoutputcommitter.algorithm.version", "2")
.config("spark.dynamicAllocation.enabled", false)
.config("spark.executor.cores", 5)
.config("spark.executors.memory", "18G")
.config("spark.yarn.executor.memoryOverhead", "2G")
.config("spark.driver.memory", "18G")
.config("spark.executor.instances", 23)
.config("spark.default.parallelism", 230)
.config("spark.sql.shuffle.partitions", 230)
.enableHiveSupport()
.getOrCreate()
数据来自CSV文件:
val ds = spark.read
.option("header", "true")
.option("delimiter", ",")
.schema(/* 2 cols: [ValidatedNel, and a stuct schema */)
.csv(sourceFromS3)
.as(MyCaseClass)
val mappedDs:Dataset[ValidatedNel, MyCaseClass] = ds.map(...)
mappedDs.repartition(230)
val count = mappedDs.count() // never finishes
正如预期的那样,它旋转了230个任务,完成了229个任务,中间只有一个。请看下面-第一个任务永远挂起,中间的任务完成时没有问题,尽管很奇怪-大小记录/比率非常不同-其他229个任务看起来与完成的任务完全相同
Index| ID |Attempt |Status|Locality Level|Executor ID / Host| Launch Time | Duration |GC Time|Input Size / Records|Write Time | Shuffle Write Size / Records| Errors
110 117 0 RUNNING RACK_LOCAL 11 / ip-XXX-XX-X-XX.uswest-2.compute.internal 2019/10/01 20:34:01 1.1 h 43 min 66.2 MB / 2289538 0.0 B / 0
0 7 0 SUCCESS PROCESS_LOCAL 9 / ip-XXX-XX-X-XXX.us-west-2.compute.internal 2019/10/01 20:32:10 1.0 s 16 ms 81.2 MB /293 5 ms 59.0 B / 1 <-- this task is odd, but finishes
1 8 0 SUCCESS RACK_LOCAL 9 / ip-XXX-XX-X-XXX.us-west-2.compute.internal 2019/10/01 20:32:10 2.1 min 16 ms 81.2 MB /2894845 9 s 59.0 B / 1 <- the other tasks are all similar to this one
另一个注意事项是,在调用count之前,我正在调用repartition230,只是在调用数据集[T]上的count之前,确保数据的平均分布
这是怎么回事?它可能与数据倾斜和/或数据解析问题有关。请注意,问题分区的记录远远多于已成功处理的分区:
Input Size / Records
66.2 MB / 2289538
81.2 MB /293
我会检查所有分区文件的大小和记录数是否大致相同。可能是问题分区文件或良好分区文件中的行和/或列分隔符关闭293行对于约80 Mb的文件来说似乎太低了。好吧-在进行计数之前,数据被加载到数据集[T],并且T字段中没有一个是选项[\u3],因此如果不是,解析将失败。我再次查看了我的输入大小和记录-81.2MB/293记录似乎不符合您的要求-但这一步完成得很好。这个想法很奇怪,因为其他228个任务都是@81.2MB/@2200000。我调用repartition230是否可以正确地重新分发数据,防止数据倾斜?您所说的加载是什么意思?Spark有一个懒惰的评估模型。所有读取/缓存/重新分区/数据转换调用仅用于构建执行计划DAG。只有在遇到计数、写入、显示等操作时才会执行。对不起,我的意思是,在计数之前,CSV引入的原始DF有一个映射转换,并将其转换为数据集[T],因为这是一个转换,不会在该步骤失败吗,而不是计数?我还应该提到,出于调试目的,我在计数之前也做了一次拍摄,这也可以正常工作。结果表明,我试图对其执行操作的文件可能已损坏。我甚至无法通过SSH进入EMR集群来运行简单的计数。给你打勾,因为最终,这是一个数据解析问题!spark.executorS.memory=…-是打字错误吗?我也会考虑缩小你的资源分配,去掉所有无关的配置选项。Skest.Existuor。内存=是一个有效的设置——它是给每个执行者多少RAM。5个核心/执行器,每个实例16个核心-守护进程1个=每个实例15个核心/5=每个实例3个执行器。实例/3执行器的61GiB内存=61GiB的20-10%,开销=18。@mazaneicha-我需要所有这些设置,因此无法删除它们。你推荐哪种资源配对?好的,执行者,单数,不是复数。您将为操作系统、节点管理器、资源管理器以及节点上运行的任何其他设备留下1个内核和1 GB的开销?这听起来太刺激了。我怀疑您是否需要default.parallelism和shuffle.pations设置。不确定你的应用程序中还发生了什么,但如上所述,它也不需要猜测或任何蜂巢。。。选项。
Input Size / Records
66.2 MB / 2289538
81.2 MB /293