我有一个应用程序,它使用大约20个RDD进行所需的计算。 可以分为两个作业:
在这20个RDD中,每个RDD使用15个,两者共享10个。
每种算法都基于时间窗口运行15次过滤。伪:
shareRdd1 = spark.read(...).cache()
...
shareRdd10 = spark.read(...).cache()
job1Rdd1 = spark.read(...).cache()
...
job1Rdd5 = spark.read(...).cache()
job2Rdd1 = spark.read(...).cache()
...
job2Rdd5 = spark.read(...).cache()
job1 = new Job1(shareRdd1, ..., shareRdd10, job1Rdd1, ..., job1Rdd5)
job2 = new Job2(shareRdd1, ..., shareRdd10, job2Rdd1, ..., job2Rdd5)
for i=0..14
job1.run(i)
job2.run(i)
每个作业都使用i
相应地从RDD中切片数据,执行一堆联接,查找等。
最后,它将数据保存到S3并将数据推入RDS。伪:
void run(int i)
var result
shareRdd1.where(<some i related slicing>)
...
join, aggregate, etc
...
result = result.cache()
result.write(...)
result.forEachPartition(<push to rds>)
result.unpersist()
我看到的问题是,随着时间的推移,整个火花提交将逐渐占用越来越多的内存。
每次作业run
时,我们都会清除所有内部结果,确保将其删除,等等(甚至尝试使用.unpersist(true)
)
唯一的在循环执行过程中保持活动的是缓存的RDD。他们需要大量的工作来加载,这就是为什么要对其进行缓存。
如果您查看01:37左右的网络高峰,那就是从存储中加载所有RDD且算法开始工作的时候。 随着循环的继续,越来越多的内存被消耗掉,直到最后作业开始停止(可能是由于磁盘的使用,因为事情不再适合内存了。)
在Spark Web界面的“存储”选项卡上查看时,我们的RDD的总大小约为3GB。
这台机器有足够的内存来处理它,我什至尝试了更大的机器,但是确实发生了。曲线是一样的。
我在做什么错?
spark = 2.3.1
emr = 5.16.0
java = 1.8
1x m4.10xlarge
--driver-memory 8g
--driver-cores 5
--conf spark.dynamicAllocation.enabled=false
--conf spark.yarn.executor.memoryOverhead=2048
--conf spark.yarn.driver.memoryOverhead=2048
--conf spark.executor.instances=14
--conf spark.executor.memory=8g
--conf spark.executor.cores=5
--conf spark.default.parallelism=140