不可不知的spark shuffle
shuffle概览
一个spark的RDD有一组固定的分区组成,每个分区有一系列的记录组成。对于由窄依赖变换(例如map和filter)返回的RDD,会延续父RDD的分区信息,以pipeline的形式计算。每个对象仅依赖于父RDD中的单个对象。诸如coalesce之类的操作可能导致任务处理多个输入分区,但转换仍然被认为是窄依赖的,因为一个父RDD的分区只会被一个子RDD分区继承。
Spark还支持宽依赖的转换,例如groupByKey和reduceByKey。在这些依赖项中,计算单个分区中的记录所需的数据可以来自于父数据集的许多分区中。要执行这些转换,具有相同key的所有元组必须最终位于同一分区中,由同一任务处理。为了满足这一要求,Spark产生一个shuffle,它在集群内部传输数据,并产生一个带有一组新分区的新stage。
可以看下面的代码片段:
上面的代码片段只有一个action操作,count,从输入textfile到action经过了三个转换操作。这段代码只会在一个stage中运行,因为,三个转换操作没有shuffle,也即是三个转换操作的每个分区都是只依赖于它的父RDD的单个分区。
但是,下面的单词统计就跟上面有很大区别:
这段代码里有两个reducebykey操作,三个stage。
下面图更复杂,因为有一个join操作:
粉框圈住的就是整个DAG的stage划分。
在每个stage的边界,父stage的task会将数据写入磁盘,子stage的task会将数据通过网络读取。由于它们会导致很高的磁盘和网络IO,所以shuffle代价相当高,应该尽量避免。父stage的数据分区往往和子stage的分区数不同。触发shuffle的操作算子往往可以指定分区数的,也即是numPartitions代表下个stage会有多少个分区。就像mr任务中reducer的数据是非常重要的一个参数一样,shuffle的时候指定分区数也将在很大程度上决定一个应用程序的性能。
优化shuffle
通常情况可以选择使用产生相同结果的action和transform相互替换。但是并不是产生相同结果的算子就会有相同的性能。通常避免常见的陷阱并选择正确的算子可以显著提高应用程序的性能。
当选择转换操作的时候,应最小化shuffle次数和shuffle的数据量。shuffle是非常消耗性能的操作。所有的shuffle数据都会被写入磁盘,然后通过网络传输。repartition , join, cogroup, 和 ?*By 或者 *ByKey 类型的操作都会产生shuffle。我们可以对一下几个操作算子进行优化:
1. groupByKey某些情况下可以被reducebykey代替。
2. reduceByKey某些情况下可以被 aggregatebykey代替。
3. flatMap-join-groupBy某些情况下可以被cgroup代替。
具体细节,知识星球球友可以点击阅读原文进入知识星球阅读。
no shuffle
在某些情况下,前面描述的转换操作不会导致shuffle。当先前的转换操作已经使用了和shuffle相同的分区器分区数据的时候,spark就不会产生shuffle。
举个例子:
由于使用redcuebykey的时候没有指定分区器,所以都是使用的默认分区器,会导致rdd1和rdd2都采用的是hash分区器。两个reducebykey操作会产生两个shuffle过程。如果,数据集有相同的分区数,执行join操作的时候就不需要进行额外的shuffle。由于数据集的分区相同,因此rdd1的任何单个分区中的key集合只能出现在rdd2的单个分区中。 因此,rdd3的任何单个输出分区的内容仅取决于rdd1中单个分区的内容和rdd2中的单个分区,并且不需要第三个shuffle。
例如,如果someRdd有四个分区,someOtherRdd有两个分区,而reduceByKeys都使用三个分区,运行的任务集如下所示:
如果rdd1和rdd2使用不同的分区器或者相同的分区器不同的分区数,仅仅一个数据集在join的过程中需要重新shuffle
在join的过程中为了避免shuffle,可以使用广播变量。当executor内存可以存储数据集,在driver端可以将其加载到一个hash表中,然后广播到executor。然后,map转换可以引用哈希表来执行查找。
增加shuffle
有时候需要打破最小化shuffle次数的规则。
当增加并行度的时候,额外的shuffle是有利的。例如,数据中有一些文件是不可分割的,那么该大文件对应的分区就会有大量的记录,而不是说将数据分散到尽可能多的分区内部来使用所有已经申请cpu。在这种情况下,使用reparition重新产生更多的分区数,以满足后面转换算子所需的并行度,这会提升很大性能。
使用reduce和aggregate操作将数据聚合到driver端,也是修改区数的很好的例子。
在对大量分区执行聚合的时候,在driver的单线程中聚合会成为瓶颈。要减driver的负载,雅思报名条件可以首先使用reducebykey或者aggregatebykey执行一轮分布式聚合,同时将结果数据集分区数减少。实际思路是首先在每个分区内部进行初步聚合,同时减少分区数,然后再将聚合的结果发到driver端实现最终聚合。典型的操作是treeReduce?和?treeAggregate。
当聚合已经按照key进行分组时,此方法特别适用。例如,假如一个程序计算语料库中每个单词出现的次数,并将结果使用map返回到driver。一种方法是可以使用聚合操作完成在每个分区计算局部map,然后在driver中合并map。可以用aggregateByKey以完全分布的方式进行统计,然后简单的用collectAsMap将结果返回到driver。
更多spark技巧,大数据技巧,欢迎点击阅读原文加入知识星球。
推荐阅读:
经验|如何设置Spark资源
戳破 | hive on spark
调优点
文章来源:https://blog.csdn.net/rlnLo2pNEfx9c/article/details/81976622
不可不知的spark shuffle的更多相关文章
- Spark Shuffle原理、Shuffle操作问题解决和参数调优
摘要: 1 shuffle原理 1.1 mapreduce的shuffle原理 1.1.1 map task端操作 1.1.2 reduce task端操作 1.2 spark现在的SortShuff ...
- spark shuffle 相关细节整理
1.Shuffle Write 和Shuffle Read具体发生在哪里 2.哪里用到了Partitioner 3.何为mapSideCombine 4.何时进行排序 之前已经看过spark shuf ...
- Spark Shuffle数据处理过程与部分调优(源码阅读七)
shuffle...相当重要,为什么咩,因为shuffle的性能优劣直接决定了整个计算引擎的性能和吞吐量.相比于Hadoop的MapReduce,可以看到Spark提供多种计算结果处理方式,对shuf ...
- Spark shuffle详细过程
有许多场景下,我们需要进行跨服务器的数据整合,比如两个表之间,通过Id进行join操作,你必须确保所有具有相同id的数据整合到相同的块文件中.那么我们先说一下mapreduce的shuffle过程. ...
- MapReduce Shuffle原理 与 Spark Shuffle原理
MapReduce的Shuffle过程介绍 Shuffle的本义是洗牌.混洗,把一组有一定规则的数据尽量转换成一组无规则的数据,越随机越好.MapReduce中的Shuffle更像是洗牌的逆过程,把一 ...
- Spark Shuffle实现
Apache Spark探秘:Spark Shuffle实现 http://dongxicheng.org/framework-on-yarn/apache-spark-shuffle-details ...
- Spark Shuffle模块——Suffle Read过程分析
在阅读本文之前.请先阅读Spark Sort Based Shuffle内存分析 Spark Shuffle Read调用栈例如以下: 1. org.apache.spark.rdd.Shuffled ...
- [Spark性能调优] 第四章 : Spark Shuffle 中 JVM 内存使用及配置内幕详情
本课主题 JVM 內存使用架构剖析 Spark 1.6.x 和 Spark 2.x 的 JVM 剖析 Spark 1.6.x 以前 on Yarn 计算内存使用案例 Spark Unified Mem ...
- spark shuffle
Spark Shuffle 1. Shuffle相关 当Map的输出结果要被Reduce使用时,输出结果需要按key哈希,并且分发到每一个Reducer上去,这个过程就是shuffle.由于shuff ...
随机推荐
- Checked exceptions: Java’s biggest mistake-检查型异常:Java最大的错误(翻译)
原文地址:http://literatejava.com/exceptions/checked-exceptions-javas-biggest-mistake/ 仅供参考,毕竟我四级都没过 Chec ...
- KNN-学习笔记
仅供学习使用 练习1 # coding:utf-8 # 2019/10/16 16:49 # huihui # ref: import numpy as np from sklearn import ...
- centos6.9下 svn 1.7.10版本 编译安装
svn安装推荐文章: 1. http://blog.51cto.com/myhat/786950 2. https://blog.csdn.net/test1280/article/det ...
- Navicat连接mysql时候出现1251错误代码
出现1251错误代码 是因为mysql8.0的密码加密方式与之前5.0的不同 如果是字母式的密码 比如root 可能会出现这种情况 1.先通过命令行进入mysql的root账户 Enter passw ...
- Linux centos7 Linux网络相关、firewalld和netfilter、netfilter5表5链介绍、iptables语法
一. Linux网络相关 yum install net-tools ifconfig查看网卡ip ifup ens33开启网卡 ifdown ens33关闭网卡 设定虚拟网卡ens33:0 mii- ...
- Java连载80-数字类格式、随机数、BigDecimal
一.数字类 1.关于数字格式化:java.text.DecimalFormat; 2.数字格式元素: # 任意数字 , 千分位 . 小数点 0 不够补零 package com.bjpowernode ...
- 为什么阿里Java规约要求谨慎使用SimpleDateFormat
前言 在阿里Java开发规约中,有强制性的提到SimpleDateFormat 是线程不安全的类 ,在使用的时候应当注意线程安全问题,如下: 其实之前已经介绍过使用JDK1.8的DateTimeFor ...
- keep-alive 用法 及activated,deactivated这两个生命周期函数
keep-aliveProps: include - 字符串或正则表达式.只有名称匹配的组件会被缓存.exclude - 字符串或正则表达式.任何名称匹配的组件都不会被缓存.max - 数字.最多可以 ...
- 【剑指Offer面试编程题】题目1505:两个链表的第一个公共结点--九度OJ
题目描述: 输入两个链表,找出它们的第一个公共结点. 输入: 输入可能包含多个测试样例. 对于每个测试案例,输入的第一行为两个整数m和n(1<=m,n<=1000):代表将要输入的两个链表 ...
- day16-Python运维开发基础(os / os.path / shutil模块)
1. OS模块与shutil模块 os :新建/删除shutil: 复制/移动 # ### os模块 与 shutil模块 """ os 新建/删除 shutil 复制/ ...