手把手教你 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/394760.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

pytorch线性回归代码_[PyTorch 学习笔记] 1.3 张量操作与线性回归

本章代码:https://github.com/zhangxiann/PyTorch_Practice/blob/master/lesson1/linear_regression.py张量的操作拼接torch.cat()torch.cat(tensors, dim0, outNone)功能:将张量按照 dim 维度进行拼接tensors: 张量序列dim: 要拼接的维度代码示例&#…

《UNIXLinux程序设计教程》一2.1 UNIX 输入输出基本概念

2.1 UNIX 输入输出基本概念 在任何一种操作系统中,程序开始读写一个文件的内容之前,必须首先在程序与文件之间建立连接或通信通道,这一过程称为打开文件。打开一个文件的目的可能是要读其中的数据,也可能是要往其中写入数据&…

c语言编常见算法,5个常见C语言算法

5个常见C语言算法十进制转换为二进制的递归程序字符串逆置的递归程序整数数位反序&#xff0c;例如12345->54321四舍五入程序(考虑正负数)二分法查找的递归函数#include#include#include//十进制转换为二进制的递归程序voidDecimalToBinary(int n){if(n<0){printf("…

利用Kinect将投影变得可直接用手操控

Finally 总算是到了这一天了&#xff01;假期里算法想不出来&#xff0c;或者被BUG折磨得死去活来的时候&#xff0c;总是YY着什么时候能心情愉快地坐在电脑前写一篇项目总结&#xff0c;今天总算是抽出时间来总结一下这神奇的几个月。 现在回过头来看&#xff0c;上学期退出AC…

springboot自动配置的原理_SpringBoot自动配置原理

SpringBoot的启动入口就是一个非常简单的run方法&#xff0c;这个run方法会加载一个应用所需要的所有资源和配置&#xff0c;最后启动应用。通过查看run方法的源码&#xff0c;我们发现&#xff0c;run方法首先启动了一个监听器&#xff0c;然后创建了一个应用上下文Configurab…

Django first lesson 环境搭建

pycharm ide集成开发环境 &#xff08;提高开发效率&#xff09; 解释器/编译器编辑器调试环境虚拟机连接 设置VirtualBox端口 操作1 操作2 点击号添加&#xff0c;名称为SSH&#xff0c;其中主机端口为物理机的端口&#xff0c;这里设置为1234&#xff0c;子系统端口为虚拟机的…

《Drupal实战》——3.3 使用Views创建列表

3.3 使用Views创建列表 我们接着讲解Views的设置&#xff0c;首先做一个简单的实例。 3.3.1 添加内容类型“站内公告” 添加一个内容类型“站内公告”&#xff0c;属性配置如表3-1所示。 为该内容类型设置Pathauto的模式news/[node:nid]&#xff0c;并且我们在这里将节点类型…

idea mybatis generator插件_SpringBoot+MyBatis+Druid整合demo

最近自己写了一个SpringBootMybatis(generator)druid的demo1. mybatisgenerator逆向工程生成代码1. pom文件pom文件添加如下内容&#xff0c;引入generator插件org.mybatis.generator mybatis-generator-maven-plugin 1.3.5 mysql …

python isalnum函数_探究Python中isalnum()方法的使用

探究Python中isalnum()方法的使用 isalnum()方法检查判断字符串是否包含字母数字字符。 语法 以下是isalnum()方法的语法&#xff1a; str.isa1num() 参数 NA 返回值 如果字符串中的所有字符字母数字和至少有一个字符此方法返回 true&#xff0c;否则返回false。 例子 下面的例…

动态规划算法——最长上升子序列

今天我们要讲的是最长上升子序列&#xff08;LIS&#xff09;。【题目描述】给定N个数&#xff0c;求这N个数的最长上升子序列的长度。【样例输入】      【样例输出】7        42 5 3 4 1 7 6那么什么是最长上升子序列呢&#xff1f; 就是给你一个序列…

如何快速掌握一门新技术/语言/框架

IT行业中的企业特点是都属于知识密集型企业。这种企业的核心竞争力与员工的知识和技能密切相关。而如果你在企业中扮演的是工程师的角色的话&#xff0c;那么 你的核心竞争力就是IT相关的知识与技能的储备情况。而众所周知&#xff0c;IT行业是一个大量产生新知识的地方&#x…

c语言今天星期几问题,C语言输入今天星期几

满意答案迷茫03222015.07.24采纳率&#xff1a;55% 等级&#xff1a;9已帮助&#xff1a;665人123456789101112131415161718192021#include<stdio.h>int main(void){ enum weekday{ sun, mon, tue, wed, thu, fri, sat }; int n; printf("输入星期数(0-…

备忘录模式 详解

定义 在不破坏封装性的前提下&#xff0c;捕获一个对象的内部状态&#xff0c;并在该对象之外保存这个状态&#xff1b; 行为型模式 角色 发起人角色&#xff08;Originator&#xff09;&#xff1a;记录当前时刻的内部状态&#xff0c;负责定义哪些属于备份范围的状态&#xf…

dll oem证书导入工具_技术干货 | 恶意代码分析之反射型DLL注入

欢迎各位添加微信号&#xff1a;qinchang_198231 加入安全 交流群 和大佬们一起交流安全技术01技术概要这是一种允许攻击者从内存而非磁盘向指定进程注入DLL的技术&#xff0c;该技术比常规的DLL注入更为隐蔽&#xff0c;因为除了不需要磁盘上的实际DLL文件之外&#xff0c;它…

锐捷亮相GITC:请互联网企业为我点个赞!

【51CTO.com原创稿件】GITC全球互联网技术大会已成功举办四届&#xff0c;今年的会议现场依然是摩肩接踵围观者众。围绕互联网热点技术&#xff0c;众人根据云、大数据、安全、运维、基础架构的不同主题&#xff0c;各自聚成小圈子展开深入交流。 锐捷的展位在主会场的内侧&…

react.lazy 路由懒加载_React lazy/Suspense使用及源码解析

React v16.6.0已经发布快一年了&#xff0c;为保障项目迭代发布&#xff0c;没有及时更新react版本&#xff0c;最近由于开启了新项目&#xff0c;于是使用新的react版本进行了项目开发。项目工程如何搭建&#xff0c;如何满足兼容性要求&#xff0c;如何规范化等等这里不作为介…

c语言数据结构系统化,C语言数据结构+数据库+操作系统

http://cv.qiaobutang.com/post/55c419b20cf2009bd4607795第二部分是专业相关的C &#xff0c;数据库&#xff0c;操作系统&#xff0c;数据结构。http://c.biancheng.net/cpp/u/shuju/数据(Data)是信息的载体&#xff0c;它能够被计算机识别、存储和加工处理。它是计算机程序加…

c语言判断一个序列是不是另一个的子序列

1 #include <stdio.h>2 #include <string.h>//添加字符串头文件3 4 int Subsequence(char s[], char t[]) 5 {6 int m,n,i,j;7 n strlen(s); //n表示序列S的长度8 m strlen(t); //m表示序列T的长度9 i0; 10 j0; 11 if (m>…

linux中python如何调用matlab的数据_特征锦囊:如何在Python中处理不平衡数据

今日锦囊特征锦囊&#xff1a;如何在Python中处理不平衡数据? Index1、到底什么是不平衡数据2、处理不平衡数据的理论方法3、Python里有什么包可以处理不平衡样本4、Python中具体如何处理失衡样本印象中很久之前有位朋友说要我写一篇如何处理不平衡数据的文章&#xff0c;整理…

Hadoop不适合哪些场景 哪些场景适合?

Hadoop设计的目的主要包括下面几个方面&#xff0c;也就是所谓的适用场景&#xff1a; 1&#xff1a;超大文件 可以是几百M&#xff0c;几百T这个级别的文件。 2&#xff1a;流式数据访问 Hadoop适用于一次写入&#xff0c;多次读取的场景&#xff0c;也就是数据复制进去之后&a…