Spark性能调优实战
吴磊
FreeWheel机器学习团队负责人
新⼈⾸单¥59.9
1298 人已学习
课程目录
已更新 19 讲 / 共 32 讲
0/4登录后,你可以任选4讲全文学习。
课前必学 (3讲)
开篇词 | Spark性能调优,你该掌握这些“套路”
免费
01 | 性能调优的必要性:Spark本身就很快,为啥还需要我调优?
02 | 性能调优的本质:调优的手段五花八门,该从哪里入手?
原理篇 (5讲)
03 | RDD:为什么你必须要理解弹性分布式数据集?
04 | DAG与流水线:到底啥叫“内存计算”?
05 | 调度系统:“数据不动代码动”到底是什么意思?
06 | 存储系统:空间换时间,还是时间换空间?
07 | 内存管理基础:Spark如何高效利用有限的内存空间?
通用性能调优篇 (11讲)
08 | 应用开发三原则:如何拓展自己的开发边界?
09 | 调优一筹莫展,配置项速查手册让你事半功倍!(上)
10 |调优一筹莫展,配置项速查手册让你事半功倍!(下)
11 | Shuffle的工作原理:为什么说Shuffle是一时无两的性能杀手?
12 | 广播变量(一):克制Shuffle,如何一招制胜!
13 | 广播变量(二):有哪些途径让Spark SQL选择Broadcast Joins?
14 | CPU视角:如何高效地利用CPU?
15 | 内存视角(一):如何最大化内存的使用效率?
16 | 内存视角(二):如何有效避免Cache滥用?
17 | 内存视角(三):OOM都是谁的锅?怎么破?
18 | 磁盘视角:如果内存无限大,磁盘还有用武之地吗?
Spark性能调优实战
15
15
1.0x
00:00/00:00
登录|注册

17 | 内存视角(三):OOM都是谁的锅?怎么破?

吴磊 2021-04-21
你好,我是吴磊。
无论是批处理、流计算,还是数据分析、机器学习,只要是在 Spark 作业中,我们总能见到 OOM(Out Of Memory,内存溢出)的身影。一旦出现 OOM,作业就会中断,应用的业务功能也都无法执行。因此,及时处理 OOM 问题是我们日常开发中一项非常重要的工作。
但是,Spark 报出的 OOM 问题可以说是五花八门,常常让人找不到头绪。比如,我们经常遇到,数据集按照尺寸估算本该可以完全放进内存,但 Spark 依然会报 OOM 异常。这个时候,不少同学都会参考网上的做法,把 spark.executor.memory 不断地调大、调大、再调大,直到内心崩溃也无济于事,最后只能放弃。
那么,当我们拿到 OOM 这个“烫手的山芋”的时候该怎么办呢?我们最先应该弄清楚的是“到底哪里出现了 OOM”。只有准确定位出现问题的具体区域,我们的调优才能有的放矢。具体来说,这个“哪里”,我们至少要分 3 个方面去看。
发生 OOM 的 LOC(Line Of Code),也就是代码位置在哪?
OOM 发生在 Driver 端,还是在 Executor 端?
如果是发生在 Executor 端,OOM 到底发生在哪一片内存区域?
定位出错代码的位置非常重要但也非常简单,我们只要利用 Stack Trace 就能很快找到抛出问题的 LOC。因此,更关键的是,我们要明确出问题的到底是 Driver 端还是 Executor 端,以及是哪片内存区域。Driver 和 Executor 产生 OOM 的病灶不同,我们自然需要区别对待。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《Spark性能调优实战》,如需阅读全部文章,
请订阅文章所属专栏新⼈⾸单¥59.9
立即订阅
登录 后留言

精选留言(5)

  • 巧克力黑
    老师好!
    实例1中
    1、为什么提到“线程池大小设置为 1 是不可取的”?

    2、假如spark.executor.cores设置成 1 ,有3个Task,串行。
    第一个Task执行完成后,360M的内存会全部都释放么?会不会有垃圾还没有回收的情况,导致Task2的内存没有360M可以

    作者回复: 1. 如果并发度是1,单个Executor就是纯粹的串行计算了,Spark“分布式”计算引擎的并行计算就失去了意义。即便还是可以有多个Executors,但是如果每个Executor在同一时间只有一个线程在工作,这种“分布式”计算的效率也是极其低下的。

    2. 好问题,确实有这个隐患。不过呢,因为任务执行涉及的对象都是short-lived,也就是生命周期都很短,不像Storage Memory存储的缓存对象、生命周期很长。因此,执行任务涉及到的对象,多是放在年轻代,Minor GC的触发会频繁一些,回收效率也更高。不像long-lived objects,往往需要触发Full GC才能回收。因此,即便有还未回收的内存,也不影响任务执行,因为Minor GC频繁、且轻量,能够相对及时地把内存回收。

    2021-04-21
    3
  • Fendora范东_
    1.task1首先运行的,拿到自己1/N发现还不够,就继续申请内存。task2/task3后面运行,发现可用内存满足下限,就跑去运行了,结果task1抢先申请到300M,task2,task3在运行时需要更多内存,不能得到满足,导致OOM。
    2.driver端oom:
    遇到过执行查询SQL,结果集太大,oom。通过调maxResultSize大小来解决。
    executor端oom:
    之前没细究过,oom了就给executor调大内存就完了。。。。😅

    作者回复: 1. 不完全对,task1之所以能拿到,是因为它“到的早”,它刚来的时候N=1,所以它最多可以拿到整个执行内存。task2、task3不行,是因为他们来得晚,他们到的时候,N至少等于2了,所以“每人”最多拿执行内存的一半,所以肯定会OOM。这里其实有点tricky,主要想考大家对于(1/N/2,1/N)的理解是不是足够透彻。

    2. 对,driver OOM调整maxResultSize比较典型。学过这一讲,Executors内存调优可以做得更细致一些了,就不必每次都是单纯调大executor.memory~

    2021-04-21
    1
  • Fendora范东_
    有个疑问
    collect是把executor所有数据全部拉回来,但是他是一次性全放到driver端吗?如果是,那fetchsize的大小只是为了分批输出吗,是不是调的越大输出就越快了;如果不是,那就不应该出现driver端oom吧
    按照文中分析来看,collect就是把所有数据一次性拉到driver端了吧?

    作者回复: collect是全量拉,你说的fetch size,我理解是单批次拉取的最大数据量,是用来限制网络吞吐的,因此这个参数和Driver是否OOM没有关系。Driver能承受的全量数据大小,由maxResultSize参数来决定,如果你拉的全量数据,大于maxResultSize,就会OOM。

    2021-04-21
    1
  • sky_sql
    老师好!麻烦问下 Shuffle 文件寻址有个参数spark.reducer.maxSizeInFlight 默认48m,这个buffer缓冲每次拉取48m数据。是Execution Memory剩余部分不够48m就会oom吗?这个和1/N的有啥关联?

    作者回复: 好问题,你说的是对的,这部分buffer也算作Execution Memory的一部分,也会记到Execution Memory的“账上”。因此,如果像你说的这种edge case,连48M都没有了,那拉数据的时候确实会OOM。这部分就没有1/N的关系了哈,每个task都是这么大的buffer,一旦不够,也就OOM了。

    2021-04-21
  • 王天雨
    1、执行内存总量是动态变化的,最大是spark.executor.memory * spark.memory.fraction
    本例中最大360M。
    其次并发度N是固定不变,但是Executor中当前并行执行的任务数是小于等于N的,
    上下限公式的计算是根据Executor中当前并行执行的并发度来计算的。
    因此先拿到任务的线程能够申请更多的资源,极端情况下,本例单个Task可享受360M内存。

    作者回复: 正解~ 赞~ 👍 老弟对于执行内存的(1/N/2,1/N)理解得相当到位~

    2021-04-21
    1
收起评论
5
返回
顶部