Spark 数据倾斜调优
一、what is a shuffle?
1.1 shuffle简介
一个stage执行完后,下一个stage开始执行的每个task会从上一个stage执行的task所在的节点,通过网络传输获取task需要处理的所有key,然后每个task对相同的key进行算子操作,这个过程就是shuffle过程。
我们常说的shuffle过程之所以慢是因为有大量的磁盘IO以及网络传输操作。spark中负责shuffle的组件主要是ShuffleManager,在spark1.1之前采用的都是HashShuffleManager,在1.1之后开始引入效果更优SortShuffleManager,并在1.2开始默认使用SortShuffleManager。
1.2 HashShuffleManager
我们来看下最初的ShuffleManager:HashShuffleManager中shuffle的读写过程
从上图我们可以看出,Executor中每个core对应的task在shuffle写的时候都会产生和下一个stage包含task数目一样的磁盘文件,也就是说下一个stage包含多少个task(即Reducer),当前stage的task就会产生多少个磁盘文件。那么100个单核的Executor,当前stage有200个task,每个Executor负责执行2个task,下一个stage有100个task,那么一次shuffle write需要产生200*100=20000个磁盘文件。每个buffer(即图中的bucket)的大小默认为32KB(Spark1.1中默认是100KB,可以通过spark.shuffle.file.buffer.kb来设置);在shuffle read阶段每个task从上一个stage中的每一个task中通过网络传输拉取相同key的数据进行聚合等shuffle操作。所以产生的磁盘文件越多,shuffle read的IO操作就越频繁,且大量的buffer将对Executor的存储空间产生巨大的压力。
Spark团队对针对“磁盘文件多”这一弊端进行了优化,优化后的HashShuffleManager的shuffle的读写过程:
从上图我们可以看出,下一个stage的每个task的入度变成了优化前的一半,主要是因为每个core都产生了和下一个stage的task相同数目的磁盘文件,同一core中的不同task复用一批磁盘文件,减少磁盘文件数据,提升shuffle write性能。那么与上面相同环境下,优化后需要产生的磁盘文件数量为Executor数*Executor的core数*下一个stage的task数=100*1*100=10000。可以通过将spark.shuffle.consolidateFiles设置为true来开启consolidate机制,即优化后的HashShuffleManager。
1.3 sortShuffleManager
Spark 1.2 后开始默认使用sortShuffleManager
SortShuffleManager主要改进点是在内存溢写到磁盘文件之前,会根据Partition id以及key对内存数据进行sort排序,然后再分批写入磁盘文件,分批的batch数量大小为1w条,最后将产生的多个磁盘文件merge成一个磁盘文件,并产生一个索引文件,用以标识下游stage中的各个task的数据在文件中的start offset 和 end offset,直观来看,一个task仅产生一个磁盘文件和一个索引文件。产生的磁盘文件少了,但增加了排序的性能开销,如果这部分在你的业务场景下开销大,那么可以选择SortShuffleManager的bypass机制。
在ShuffleManager一路优化的过程中,一个重要优化思想其实就是在减少shuffle过程中产生磁盘文件数量,一个直观的逻辑:磁盘文件少,上下游stage需要进行的磁盘IO操作就相对少了。而磁盘文件过多会带来以下问题:
如果磁盘文件多,进行shuffle操作时需要同时打开的文件数多,大量的文件句柄和写操作分配的临时内存将对内存和GC带来压力,特别是在YARN的模式下,往往Executor分配的内存不足以支持这么大的内存压力;
如果磁盘文件多,那么其所带来的随机读写需要多次磁盘寻道和旋转延迟,比顺序读写的时间多许多倍。
可以通过Spark.shuffle.manager参数来设置使用哪种shuffle manager。
以上我们介绍了what is a shuffle,shuffle write 与 shuffle read的过程,以及为什么shuffle对spark任务性能消耗大,在整体上了解shuffle之后,我们来了解下如何handle shuffle。
二、判断定位
spark web ui 上task的执行时间或分配的数据量,如果一般task执行时间只有几秒,而某些task执行时间是几分钟甚至更久,那这部分task对于的stage就出现了数据倾斜,根据之前的stage的划分方式即可定位哪段代码中的算子导致了数据倾斜。
常见的触发shuffle操作的算子:distinct、groupByKey、reduceByKey、aggregateByKey、join、cogroup、repartition等
三、深究key分布
如果是数据倾斜的数据来源于hive表,那么我们可以分析下spark sql中key的数据分布情况
如果数据来源于中间的RDD,那么可以使用RDD.countByKey()来统计不同key出现的次数
如果数据量大,可以使用采样来分析,比如:
val sampledRDD = shuffleRDD.sample(false, 0.1)
val sampledKeyCounts = sampledRDD.countByKey()
sampledKeyCounts.foreach(println(_))
四、How to fix it?
数据来源于hive表,将导致数据倾斜的shuffle算子前置到**hive ETL(提取、转换和加载)**中,之后的spark任务可反复基于hive ETL后的中间表,保证了spark任务的性能。适用于多次数据计算,且对spark性能要求高的场景。
不是所有的数据都有用,如果filter少数几个数据量大的key不影响数据结果,那在数据预处理的时候可以进行过滤,或者需要动态判定key是否有用,可以在数据计算前对RDD进行sample采样,过滤数据量大的key,这样不仅可以避免数据倾斜,也可以避免相同的代码在某天突然OOM的情况,有可能这一天有某个平时表现正常的key暴增导致OOM。
shuffle算子并行操作,我们知道在shuffle过程中,分布在不同task的相同key的数据会通过网络传输到同一个task进行shuffle计算,这时候一个task可能会处理多种key的数据,比如k1,k2,k3可能都被拉取到某一个task上进行reduce操作,如果k1,k2,k3的数量比较大,我们可以通过提高reduce的并行度来使得k1,k2,k3的数据分别拉取到t1,t2,t3三个task上计算,怎么做呢?如果是RDD的shuffle操作,给shuffle算子传入一个参数即可,比如reduceByKey(600),如果是Spark SQL的shuffle操作,配置一个shuffle参数:spark.sql.shuffle.partitions,该参数表示shuffle read task的并行度,默认200,可根据业务场景进行修改。
key 散列设计再聚合,spark的shuffle操作导致的数据倾斜问题在一定意义上可以类比HBase的热点问题,因此HBase的rowkey的散列设计思想可以套用在聚合类的shuffle操作导致的数据倾斜的场景,怎么做呢?先对key进行hash散列,可以使用随机数,也可以针对key的具体内容进行hash,目的是将原本数据量大的key先hash成k个的key,那么原本必须拉取到一个task上进行shuffle计算的数据可以拉取到k个不同的task上计算,在一定程度上可以缓解单个task处理过多数据导致的数据倾斜,然后再对局部聚合后的key去除hash再聚合。这种key散列设计思想在解决join的shuffle操作广泛使用。
”map join replace “reduce join”,如果join操作是大小表的join,可以考虑将小表广播,首先collect到driver的内存中,为其创建一个broadcase变量,这时候Driver和每个Executor都会保存一份小表的全量数据,再在map操作中自定义join的逻辑,在这个join逻辑里,使用已在内存中的全量的小表数据与大表的每一条数据进行key对比连接,用map join来代替普通的reduce join,可以避免数据倾斜。由于需要在内存中存放全量小表,所以小表数据量在一两G是可取的。
Spark 数据倾斜调优的更多相关文章
- 最详细10招Spark数据倾斜调优
最详细10招Spark数据倾斜调优 数据量大并不可怕,可怕的是数据倾斜 . 数据倾斜发生的现象 绝大多数 task 执行得都非常快,但个别 task 执行极慢. 数据倾斜发生的原理 在进行 shuff ...
- Spark学习之路 (九)SparkCore的调优之数据倾斜调优
摘抄自:https://tech.meituan.com/spark-tuning-pro.html 数据倾斜调优 调优概述 有的时候,我们可能会遇到大数据计算中一个最棘手的问题——数据倾斜,此时Sp ...
- Spark(十)Spark之数据倾斜调优
一 调优概述 有的时候,我们可能会遇到大数据计算中一个最棘手的问题——数据倾斜,此时Spark作业的性能会比期望差很多.数据倾斜调优,就是使用各种技术方案解决不同类型的数据倾斜问题,以保证Spark作 ...
- Spark性能优化:数据倾斜调优
前言 继<Spark性能优化:开发调优篇>和<Spark性能优化:资源调优篇>讲解了每个Spark开发人员都必须熟知的开发调优与资源调优之后,本文作为<Spark性能优化 ...
- Spark学习之路 (九)SparkCore的调优之数据倾斜调优[转]
调优概述 有的时候,我们可能会遇到大数据计算中一个最棘手的问题--数据倾斜,此时Spark作业的性能会比期望差很多.数据倾斜调优,就是使用各种技术方案解决不同类型的数据倾斜问题,以保证Spark作业的 ...
- Spark性能优化--数据倾斜调优与shuffle调优
一.数据倾斜发生的原理 原理:在进行shuffle的时候,必须将各个节点上相同的key拉取到某个节点上的一个task来进行处理,比如按照key进行聚合或join等操作.此时如果某个key对应的数据量特 ...
- Spark面试题(五)——数据倾斜调优
1.数据倾斜 数据倾斜指的是,并行处理的数据集中,某一部分(如Spark或Kafka的一个Partition)的数据显著多于其它部分,从而使得该部分的处理速度成为整个数据集处理的瓶颈. 数据倾斜俩大直 ...
- 【转】数据倾斜是多么痛?spark作业/面试/调优必备秘籍
原博文出自于: http://sanwen.net/a/gqkotbo.html 感谢! 来源:数盟 调优概述 有的时候,我们可能会遇到大数据计算中一个最棘手的问题——数据倾斜,此时Spark作业的性 ...
- 【Spark篇】---Spark调优之代码调优,数据本地化调优,内存调优,SparkShuffle调优,Executor的堆外内存调优
一.前述 Spark中调优大致分为以下几种 ,代码调优,数据本地化,内存调优,SparkShuffle调优,调节Executor的堆外内存. 二.具体 1.代码调优 1.避免创建重复的RDD,尽 ...
随机推荐
- 爬虫实战【3】Python-如何将html转化为pdf(PdfKit)
前言 前面我们对博客园的文章进行了爬取,结果比较令人满意,可以一下子下载某个博主的所有文章了.但是,我们获取的只有文章中的文本内容,并且是没有排版的,看起来也比较费劲... 咋么办的?一个比较好的方法 ...
- 170626、springboot编程之静态资源文件
Spring Boot 默认为我们提供了静态资源处理,使用 WebMvcAutoConfiguration 中的配置各种属性. 建议大家使用Spring Boot的默认配置方式,如果需要特殊处理的再通 ...
- PL/SQL编程基础(四):程序控制(IF,CASE,FOR,LOOP,WHILE LOOP,EXIT,CONTINUE)
程序控制 程序结构有分支结构与循环结构: 分支结构语法:IF.CASE: 循环结构:FOR.WHILE LOOP:先执行再判断,至少执行一次: WHILE LOOP:先判断再执行,如果不满足条件,就不 ...
- Servlet + JSP 时代
Spring,Django,Rails,Express这些框架技术的出现都是为了解决什么问题,现在这些框架都应用在哪些方面? - 知乎 https://www.zhihu.com/question/2 ...
- spring boot由浅入深(二)spring boot基本命令及操作
一 spring常见注解 @RestController和@RequestMapping说明: @RestController.这被称为一个构造型(stereotype)注解.它为阅读代码的人们提供建 ...
- Windows环境下手动更新boot2docker.iso
GitHub连不上导致自动更新失败. https://github.com/boot2docker/boot2docker/releases 替换了DockerToolbox安装目录和系统盘用户目录\ ...
- IDEA安装以及项目初始化
首先安装idea: 如果15.0版本安装不上就安装16.0: 点击安装文件以后,一直点下一步就可以了. 安装完成后设置: 如果没有的话,需要点击SDKs,点击+,然后选择电脑上安装的JDK. 接下来创 ...
- Windows版本搭建安装React Native环境配置
1 安装Chocolatey 打开cmd黑窗口 @powershell -NoProfile -ExecutionPolicy Bypass -Command "iex ((new-obje ...
- django之中间件、缓存、信号、admin内置后台
目录: 中间件 缓存 信号 admin后台 一.中间件 1.什么是中间件? 中间件是一个.一个的管道,如果相对任何所有的通过Django的请求进行管理都需要自定义中间件 中间件可以对进来的请求和出去的 ...
- #ifdef和#if defined的差别
注意两者都有个define的作用,区别在于使用方式上.前者的通常用法是:#ifdef XXX .... #else .... #endif 只能在两者中选择是否有定义.对于后者,常用法是: #if ...