我正在运行 pyspark 应用程序,并且一直收到错误:由于超出内存限制,容器被YARN杀死。使用5.1 GB的5 GB物理内存。
hdfs中有两个数据集, 数据集A如下所示:
a0,{"count":0, "ip":"0.0.0.0"}
a1,{"count":1, "ip":"0.0.0.0"}
a1,{"count":1, "ip":"0.0.0.1"}
a2,{"count":2, "ip":"0.0.0.0"}
a3,{"count":3, "ip":"0.0.0.0"}
...
数据集B看起来像这样:
a0,{"count":0, "ip":"0.0.0.0"}
a1,{"count":1, "ip":"0.0.0.0"}
...
它们都是键,值格式sequenceFile,我想通过键加入A和B,这样我就可以获得如下结果:
a0,{"count":0, "ip":"0.0.0.0"}
a1,{"count":1, "ip":"0.0.0.0"}
a1,{"count":1, "ip":"0.0.0.1"}
并将结果保存为可读格式文件,如textfile或json或csv。
首先我使用cogroup:
rddresult = rddA.cogroup(rddB).filter(lambda x: x[1][0] and x[1][1])
我也使用join:
rddresult = rddA.join(rddB)
但都会遇到内存错误。 然后我想,这可能与groupByKey有关吗?因为它们都使用groupByKey底层。 所以我改变了我的代码,如下所示:
def mergeSeq(a, b):
ta = type(a)
tb = type(b)
if ta == list:
res = a
else:
res = [a]
if tb == list:
res.extend(b)
else:
res.append(b)
return res
def filterSeq(li):
# filtering rows that have no value from rddB
if type(li) != list:
return False
if len(li) <= 1:
return False
elif install_pair_flag in li: # install_pair_flag comes from rddB
return True
else:
return False
rddresult = rddA.union(rddB).reduceByKey(mergeSeq).filter(filterSeq)
# repartition seems to solve memory error but dramatically slow down the speed
# rddresult = rddA.union(rddB).reduceByKey(mergeSeq).filter(filterSeq).repartition(numPartitions=9092)
再次出现内存错误。
我会根据article,
的说明调整我的火花配置spark-submit --master yarn-cluster --name yy-adtracking --conf spark.akka.frameSize=2000 --conf spark.yarn.maxAppAttempts=1 --conf spark.yarn.executor.memoryOverhead=12000 --num-executors 24 --driver-memory 4g --executor-memory 2g --executor-cores 1 runjob.py
但它没有帮助。
最后,我将rdd转换为dataframe:
sqlctx = SQLContext(SC)
dfA = sqlctx.createDataFrame(rddA, ["k", "v0"])
dfB = sqlctx.createDataFrame(rddB, ["k", "v1"])
dfresult = dfA.join(dfB, on="k", how="inner")
dfresult.write.json(path, "overwrite")
好吧,它没有报告内存错误,也更快。
但是当把json写入磁盘时,它变得非常慢,几乎是计算的四倍。
所以这是我的问题: 有没有更稳定合理的快速解决方案来完成我的任务?或者我应该坚持使用当前的方法,使用重新分区或数据框?