You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spark代码运行时Python内核因内存问题崩溃,原因何在?

Spark循环运行内存崩溃问题排查与解决

代码与运行方式

自定义函数

import pandas as pd
import pyspark.sql.functions as F
import numpy as np

def my_func():
    df = pd.DataFrame(
        np.random.randn(1000000, 100)
    )
    y = spark.createDataFrame(dd) # 10 X 1k(注:此处dd未定义,疑为笔误)
    y2 = y.select(F.sum(F.col("1")))
    y3 = y2.collect()
    y2.unpersist(blocking=True)
    y2 = None
    return y3

循环执行代码

list_of_results = []
for i in range(100):
    list_of_results.append(my_func())

错误信息

Fatal error: The Python kernel is unresponsive.

The Python process exited with an unknown exit code.

环境与内存情况

  • 集群总可用内存28GB(2个worker节点,单节点分配14GB)
  • 崩溃前内存使用符合预期,未出现持续暴涨的情况

问题原因分析

  1. Python端内存泄漏:每次迭代生成的100万行×100列的Pandas DataFrame(约760MB),理论上函数结束后会被GC回收,但Python GC存在延迟,加上循环中可能有隐式引用残留,导致内存逐步累积,最终撑爆Python进程。
  2. 变量定义错误:代码中spark.createDataFrame(dd)的dd未定义,若实际运行中是动态生成的对象,可能存在引用未及时释放的问题。
  3. 结果列表内存累积:list_of_results持续收集每次collect()的结果,随着迭代次数增加,内存占用不断升高。
  4. Py4J桥接对象引用残留:Spark对象(如DataFrame)通过Py4J与JVM交互,即使调用unpersist,Python端的桥接对象可能仍持有引用,导致JVM资源无法及时释放,间接影响Python进程内存。

解决方案

1. 显式清理大对象并触发GC

在函数内显式删除大对象,强制触发Python垃圾回收,减少内存残留:

import gc

def my_func():
    df = pd.DataFrame(np.random.randn(1000000, 100))
    y = spark.createDataFrame(df) # 修正dd为df的笔误
    y2 = y.select(F.sum(F.col("1")))
    y3 = y2.collect()
    
    # 清理Spark对象
    y2.unpersist(blocking=True)
    del y, y2
    
    # 清理Pandas大对象并触发GC
    del df
    gc.collect()
    
    return y3

2. 避免结果全量存储

如果不需要保留所有迭代结果,改用生成器按需处理,减少内存占用:

def generate_results():
    for i in range(100):
        yield my_func()

# 逐个处理结果,不存储全部
for res in generate_results():
    # 此处添加结果处理逻辑
    pass

3. 优化Spark操作模式

将循环内的重复创建DataFrame操作改为批量分布式计算,减少Python与JVM的交互开销:

# 一次性生成全量数据并转为Spark DataFrame
total_df = pd.DataFrame(np.random.randn(1000000 * 100, 100))
spark_total_df = spark.createDataFrame(total_df)

# 直接在Spark上完成聚合,避免循环collect
result = spark_total_df.select(F.sum(F.col("1"))).collect()

4. 调整Python进程内存配额

若使用Notebook环境,增加Python内核的内存限制,避免因内存阈值过低导致内核崩溃。

5. 检查并清理Py4J引用

确保所有Spark相关对象在使用后被显式删除,避免Py4J桥接对象持有JVM资源,可通过del关键字删除所有Spark对象后触发GC。

内容的提问来源于stack exchange,提问作者ThomasWear

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 09:55:22