我的群集: 9个奴隶,每个100GB内存和320GB硬盘。每个主机有16个核心。我在每个主机上启动了15个spark执行器,因此每个执行器的可用内存为6GB。 我的应用:
val rdd1 = sc.textFile("a big file in S3. about 200GB" with 14M rows)
val rdd2 = sc.textFile("another big file in S3. about 200GB" with 14M rows)
val par = new HashPartitioner(150)
val rdd1Paired = rdd1.map(regular expression to get one string from each row).filter(non matched rows).partitionBy(par)
val rdd2Paired = rdd2.mpa(regular expression to get one string from each row).filter(non matched rows).partitionBy(par)
val rdd3 = rdd1.join(rdd2, par)
rdd3.count()
我从spark UI中得知这份工作分三个阶段进行了安排。过滤rdd1,过滤rdd2和计数。虽然filtering1和filtering2成功但计数总是因OOM而失败。奇怪的是,工作总是挂在计数阶段(149/150)。我检查了分配了TID150的执行程序,看到随机读取的显着增加。由于OOM,它会在一段时间后崩溃。我还看到GC经常发生在执行者身上。
问题在这里: 为什么只有一个执行程序正在获取所有数据(我检查了执行程序正在执行的最后一个操作是启动获取工作)?据我所知,一旦我为两个RDD使用相同的分区器,它们将被共同分区。并在同一工作中启动它们可确保数据的共同定位。因此,加入应该发生在每个执行者本身。前149个任务很快退出,似乎没有做任何事情。看起来最后一项任务是尝试所有的工作。
答案 0 :(得分:2)
键的分布不均匀。检查以确保没有任何过滤器功能具有导致更高浓度的某些键的附带效果。
答案 1 :(得分:0)
我猜你从数据中生成的密钥的分布是偏斜的,因此很多密钥最终会出现在同一个分区中。
它是最后一个失败的任务,它是最大的,因此它执行时间最长,并且成为最后一个。
要解决此问题,请增加分区数量和/或增加服务器数量