EMR集群并行运行多Spark应用性能异常问题咨询
Spark多应用并行运行性能异常问题解答
问题1:为何部分应用可正常快速完成,其余应用无法达到同等运行效率?
核心原因是资源配置锁死导致集群整体过载,先提交的应用抢占全部资源,后提交的应用长期处于资源饥饿状态:
- 你将
spark.dynamicallocation.minExecutor与spark.dynamicallocation.maxExecutor均设置为10,完全关闭了动态资源分配的弹性能力,每个应用启动后会固定申请10个Executor,不会因空闲释放资源,也不会在集群资源不足时降低申请量。按配置单Executor占5核+10G内存(9G堆内+1G堆外),单应用固定占用50核+100G计算资源,20个应用总资源需求为1000核+2000G内存,远超集群192核、1024G的总容量。 - 集群资源调度遵循先到先得逻辑:最早提交的少数应用能抢到足额10个Executor,因此20分钟左右即可完成;后续提交的应用只能等前置应用释放资源,长期仅能分配到12个Executor,对应同时只能运行110个任务,运行时长被拉长到2小时以上。
- 额外资源挤占:你为每个Driver配置了9核+10G内存,20个应用仅Driver进程就需要180核+200G内存,扣掉操作系统、EMR基础服务的预留资源,实际可分配给Executor的CPU核数不足170,进一步加剧了资源争抢。
问题2:已设置spark.sql.shuffle.partitions=40,为何单应用会生成约350个任务,该现象是否与spark.default.parallelism参数有关?
该现象确实和spark.default.parallelism直接相关,核心原因是两个参数的作用范围不同:
- EMR自动设定的
spark.default.parallelism=384计算规则为Worker节点总可用CPU核数的2倍,你的2台Worker总核数为192,2倍取值刚好为384,属于平台默认配置。该参数控制RDD算子、非Shuffle转换阶段的默认分区数,不受spark.sql.shuffle.partitions影响。 spark.sql.shuffle.partitions=40仅控制Spark SQL/DataFrame API触发的Shuffle阶段分区数,不覆盖全链路所有阶段:比如初始读取源数据阶段,如果没有显式重分区,分区数会继承存储层文件块数,或默认取spark.default.parallelism值;map、filter这类不触发Shuffle的转换算子,会直接继承父RDD的分区数,也不会应用40的分区配置。- 你观察到的350个左右任务,是各阶段任务数的总和:比如读入阶段生成310个左右任务,后续Shuffle阶段生成40个任务,加总后总任务数就在350上下,属于正常表现。
问题3:任务面板中显示Task 0处理数据量约1.4GB、Task 1约1.3GB,该显示是否为面板的正常展示逻辑,还是存在数据分区不均问题?
这是Spark UI的正常展示逻辑,不存在数据分区不均:
- 任务面板的单任务输入数据量,统计口径是任务读取的存储层压缩态文件块大小;而Spark SQL页的处理数据量,统计口径是解压后、经过列裁剪/行过滤后的有效计算数据,二者统计口径存在本质差异。
- 你已经观察到各分区执行耗时相近,可完全排除数据倾斜问题:如果真的存在单分区1.4GB、其余分区仅几MB的倾斜情况,大分区的执行耗时会是小分区的数十上百倍,不可能保持耗时相近。
问题4:Executor汇总标签页中显示单Executor接收数据量超过1.4GB,但Spark SQL标签页显示单应用仅处理1.5GB数据,该数值差异是否为Executor面板的正常展示逻辑?
这是Executor面板的正常统计逻辑,不存在统计错误:
- Executor标签页的接收数据量,统计口径是Executor从磁盘、网络读取的所有原始字节数,包括读取的源文件块、拉取的Shuffle数据、广播变量、内部状态同步流量等;而Spark SQL标签页的1.5GB,是实际参与SQL计算的有效逻辑数据量,统计时会剔除解码开销、广播变量、冗余读取等非计算流量,二者口径完全不同。
- 你的单应用数据量仅1.5GB,在资源不足的情况下,大部分数据会被调度到少数已分配的Executor上读取,因此单个Executor的读取数据量会接近总数据规模,和你观察到的1.4GB数值吻合。比如使用广播Join时,广播变量会被下发到所有持有数据的Executor,这部分流量也会计入Executor接收量,但不会计入SQL页的处理数据量,进一步放大数值差。
内容的提问来源于stack exchange,提问作者sriparth
相关产品推荐
相关产品推荐

