手把手教你 Spark 性能调优

 

0、背景

集群部分 spark 任务执行很慢,且经常出错,参数改来改去怎么都无法优化其性能和解决频繁随机报错的问题。

看了下任务的历史运行情况,平均时间 3h 左右,而且极其不稳定,偶尔还会报错:

1、优化思路

任务的运行时间跟什么有关?

(1)数据源大小差异

在有限的计算下,job的运行时长和数据量大小正相关,在本例中,数据量大小基本稳定,可以排除是日志量级波动导致的问题:

(2)代码本身逻辑缺陷

比如代码里重复创建、初始化变量、环境、RDD资源等,随意持久化数据等,大量使用 shuffle 算子等,比如reduceByKey、join等算子。

在这份100行的代码里,一共有 3 次 shuffle 操作,任务被 spark driver 切分成了 4 个 stage 串行执行,代码位置如下:

咱们需要做的就是从算法和业务角度尽可能减少 shuffle 和 stage,提升并行计算性能,这块是个大的话题,本次不展开详述。

(3)参数设置不合理

这块技巧相对通用,咱们来看看之前的核心参数设置:


  1. num-executors=10 || 20 ,executor-cores=1 || 2, executor-memory= 10 || 20,driver-memory=20,spark.default.parallelism=64 

假设咱们的 spark 队列资源情况如下:


  1. memory=1T,cores=400 

参数怎么设置在这里就有些技巧了,首先得明白 spark 资源的分配和使用原理:

在默认的非动态资源分配场景下, spark 是预申请资源,任务还没起跑就独占资源,一直到整个 job 所有 task 结束,比如你跳板机起了一个 spark-shell 一直没退出,也没执行任务,那也会一直占有所有申请的资源。(如果设置了 num-executors,动态资源分配会失效)

注意上面这句话,spark 的资源使用分配方式和 mapreduce/hive 是有很大差别的,如果不理解这个问题就会在参数设置上引发其它问题。

比如 executor-cores 设多少合适?少了任务并行度不行,多了会把整个队列资源独占耗光,其他同学的任务都无法执行,比如上面那个任务,在 num-executors=20 executor-cores=1 executor-memory= 10 的情况下,会独占20个cores,200G内存,一直持续3个小时。

那针对本case中的任务,结合咱们现有的资源,如何设置这 5 个核心参数呢?

1) executor_cores*num_executors 不宜太小或太大!一般不超过总队列 cores 的 25%,比如队列总 cores 400,最大不要超过100,最小不建议低于 40,除非日志量很小。

2) executor_cores 不宜为1!否则 work 进程中线程数过少,一般 2~4 为宜。

3) executor_memory 一般 6~10g 为宜,最大不超过 20G,否则会导致 GC 代价过高,或资源浪费严重。

4) spark_parallelism 一般为 executor_cores*num_executors 的 1~4 倍,系统默认值 64,不设置的话会导致 task 很多的时候被分批串行执行,或大量 cores 空闲,资源浪费严重。

5) driver-memory 早前有同学设置 20G,其实 driver 不做任何计算和存储,只是下发任务与yarn资源管理器和task交互,除非你是 spark-shell,否则一般 1-2g 就够了。

Spark Memory Manager:

6)spark.shuffle.memoryFraction(默认 0.2) ,也叫 ExecutionMemory。这片内存区域是为了解决 shuffles,joins, sorts and aggregations 过程中为了避免频繁IO需要的buffer。如果你的程序有大量这类操作可以适当调高。

7)spark.storage.memoryFraction(默认0.6),也叫 StorageMemory。这片内存区域是为了解决 block cache(就是你显示调用dd.cache, rdd.persist等方法), 还有就是broadcasts,以及task results的存储。可以通过参数,如果你大量调用了持久化操作或广播变量,那可以适当调高它。

8)OtherMemory,给系统预留的,因为程序本身运行也是需要内存的, (默认为0.2)。Other memory在1.6也做了调整,保证至少有300m可用。你也可以手动设置 spark.testing.reservedMemory . 然后把实际可用内存减去这个reservedMemory得到 usableMemory。 ExecutionMemory 和 StorageMemory 会共享usableMemory * 0.75的内存。0.75可以通过 新参数 spark.memory.fraction 设置。目前spark.memory.storageFraction 默认值是0.5,所以ExecutionMemory,StorageMemory默认情况是均分上面提到的可用内存的。

例如,如果需要加载大的字典文件,可以增大executor中 StorageMemory 的大小,这样就可以避免全局字典换入换出,减少GC,在这种情况下,我们相当于用内存资源来换取了执行效率。

最终优化后的参数如下:

效果如下:

(4)通过执行日志分析性能瓶颈

最后的任务还需要一个小时,那这一个小时究竟耗在哪了?按我的经验和理解,一般单天的数据如果不是太大,不涉及复杂迭代计算,不应该超过半小时才对。

由于集群的 Spark History Server 还没安装调试好,没法通过 spark web UI 查看历史任务的可视化执行细节,所以我写了个小脚本分析了下前后具体的计算耗时信息,可以一目了然的看到是哪个 stage 的问题,有针对性的优化。

可以看到优化后的瓶颈主要在最后写 redis 的阶段,要把 60G 的数据,25亿条结果写入 redis,这对 redis 来说是个挑战,这个就只能从写入数据量和 kv 数据库选型两个角度来优化了。

(5)其它优化角度

当然,优化和高性能是个很泛、很有挑战的话题,除了前面提到的代码、参数层面,还有怎样防止或减少数据倾斜等,这都需要针对具体的场景和日志来分析,此处也不展开。

2、spark 初学者的一些误区

对于初学者来说 spark 貌似无所不能而且高性能,甚至在某些博客、技术人眼里 spark 取代 mapreduce、hive、storm 分分钟的事情,是大数据批处理、机器学习、实时处理等领域的银弹。但事实确实如此吗?

从上面这个 case 可以看到,会用 spark、会调 API 和能用好 spark,用的恰到好处是两码事,这要求咱们不仅了解其原理,还要了解业务场景,将合适的技术方案、工具和合适的业务场景结合——这世上本就不存在什么银弹。。。

说道 spark 的性能,想要它快,就得充分利用好系统资源,尤其是内存和CPU:核心思想就是能用内存 cache 就别 spill 落磁盘,CPU 能并行就别串行,数据能 local 就别 shuffle。

本文作者:xrzs

来源:51CTO

时间: 2024-10-22 22:12:05

手把手教你 Spark 性能调优的相关文章

## Spark作业性能调优总结

Spark作业性能调优总结 前段时间在集群上运行Spark作业,但是发现作业运行到某个stage之后就卡住了,之后也不再有日志输出.于是开始着手对作业进行调优,下面是遇到的问题和解决过程: 运行时错误 Out Of Memory: Java heap space / GC overhead limit exceeded 使用yarn logs -applicationId=appliation_xxx_xxx 命令查看Yarn收集的各个Executor的日志. 可以发现OOM的错误,以及一些re

数据倾斜是多么痛?spark作业调优秘籍

调优概述 有的时候,我们可能会遇到大数据计算中一个最棘手的问题--数据倾斜,此时Spark作业的性能会比期望差很多.数据倾斜调优,就是使用各种技术方案解决不同类型的数据倾斜问题,以保证Spark作业的性能. 数据倾斜是多么痛?!!! 如果数据倾斜没有解决,完全没有可能进行性能调优,其他所有的调优手段都是一个笑话.数据倾斜是最能体现一个spark大数据工程师水平的性能调优问题. 数据倾斜如果能够解决的话,代表对spark运行机制了如指掌. 数据倾斜俩大直接致命后果. 数据倾斜直接会导致一种情况:O

oracle数据库性能调优技术:深入理解单表执行计划

一.概述 这篇文章是数据库性能调优技术的第二篇.上一篇讲解的索引调优是数据库性能调优技术的基础.这篇讲解的深入理解单表执行计划,是数据库性能调优的有力工具. 查询语句可以有多种可选执行计划,如何选择效率最高的执行计划?达梦数据库.oracle数据库.sql server数据库都是采用基于成本的查询优化,对备选执行计划进行打分,选择大家最小的执行计划进行执行.这些内容,我会在后续的几篇文章中进行详细的描述.在此之前,我们首先需要掌握如何理解数据库执行计划.这篇文章讲解只涉及单表操作的执行计划. 达

Liferay前端性能调优(1) 测评工具YSlow

最近我们团队要问Liferay做前端页面调优,当然了,测评工具是最重要的,为了看具体的页面加载时间等 ,我们首选当然是Chrome浏览器的诊断工具,但是总感觉不专业,基于我已有的经验,我还是推荐了YSlow,它 会对于页面的各项指标进行打分,然后最终获得总分然后评级,一般级别有A,B,C,D,E,F6个级别. 如何安 装和测试YSlow: (1) 从Firefox的Add-on上下载 "YSlow" (2)重启Firefox检查是否YSlow 已经被正确的安装 (3)到我们要测试的页面

数据库性能调优技术

一.概述 随着数据库在各个领域的使用不断增长,越来越多的应用提出了高性能的要求.数据库性能调优是知识密集型的学科,需要综合考虑各种复杂的因素:数据库缓冲区的大小.索引的创建.语句改写等等.总之,数据库性能调优的目的在于使系统运行得更快. 调优需要有广泛的知识,这使得它既简单又复杂. 说调优简单,是因为调优者不必纠缠于复杂的公式和规则.许多学术界和业界的研究者都在尝试将调优和查询处理建立在数学基础之上. 称调优复杂,是因为如果要完全理解常识所依赖的原理,还需要对应用.数据库管理系统.操作系统以及硬

可预见的Oracle应用程序的性能调优

这篇技巧性文章是由"国际Oracle用户组"(IOUG)提供的,它是一个由用户组成的组织,这个组织通过提供高质量的信息.培训.网络和支持,来提高Oracle数据库专家和数据库开发者的水平.这篇文章摘自由David Welch所写的论文<可预见的Oracle应用程序性能调优>.点击这里成为"国际Oracle用户组"的一员,从而获得成千上万的由Oracle用户写的技巧性文章和科技文献. 引言 我们见到过很多带有巨大性能问题的Oracle应用程序和电子商务套件

oracle数据库性能调优技术:索引调优

一.概述 随着数据库在各个领域的使用不断增长,越来越多的应用提出了高性能的要求.数据库性能调优是知识密集型的学科,需要综合考虑各种复杂的因素:数据库缓冲区的大小.索引的创建.语句改写等等.总之,数据库性能调优的目的在于使系统运行得更快. 调优需要有广泛的知识,这使得它既简单又复杂. 说调优简单,是因为调优者不必纠缠于复杂的公式和规则.许多学术界和业界的研究者都在尝试将调优和查询处理建立在数学基础之上. 称调优复杂,是因为如果要完全理解常识所依赖的原理,还需要对应用.数据库管理系统.操作系统以及硬

oracle数据库性能调优技术:深入理解嵌套循环执行计划

一.概述 这篇文章是数据库性能调优技术的第三篇.上一篇文章讲解了深入了解单表执行计划,单表执行计划是理解多表执行计划的基础. 两张表的连接有三种执行方式:1)嵌套循环连接:2)散列连接:3)归并连接.两张表连接时选择这三种中的哪一种呢?这取决于索引.以及连接的代价.在该系列的第三篇(本文)文章中讲解嵌套循环连接,第四篇文章中讲解散列连接,第五篇文章中讲解归并连接.在第六篇以后会分析IN子查询以及EXISTS子查询. 达梦数据库.oracle数据库.sql server数据库在数据库执行计划方面并

oracle数据库性能调优技术:深入理解散列连接执行计划

一.概述 这篇文章是数据库性能调优技术系列的第四篇.上一篇文章讲解了深入理解嵌套循环连接执行计划. 上一篇文章中提到两张表的连接有三种执行方式:1)嵌套循环连接:2)散列连接:3)归并连接.散列连接是很重要的连接方式,包含比较多的内容,这篇文章中讲解为什么需要散列连接?如何理解散列连接? 和前三篇文章一样,本文讲解的是些比较抽象的内容,不拘泥于具体的数据.所以本文中使用的代价评估模型也是抽象的,假设了数据库缓冲区大小只有一个页,新页的读取必然导致旧页的释放.读完本文之后应该能够读懂达梦数据库.o