spark shuffle有四种方式,分别是

  1. hashshuffle
  2. 优化后的hashshuffle
  3. sortshuffle
  4. bypass

一、hashshuffle与优化

一开始spark的shuffle方式是hashshuffle。hashshuffle有一个严重的问题,就是产生的小文件数量比较多。

我们知道,shuffle分为map端的shuffle write 和reduce端的shuffle read。

hashshuffle,每个task为下游每一个task都创建了一个文件,所以就产生了M*R的小文件数量,其中M是map的task数量,R是reduce的数量。

为了减少小文件的数量,spark随后提出了优化后的hashshuffle,即每个core处理的task文件的结果合并起来

比如:task1 write了3个小文件,里面是keyA keyB keyC,分别叫BlockA BlockB BlockC 吧

这时又来了一个task2,优化前task2 也产生三个小文件BlockA BlockB BlockC。这样就有6个小文件

但是task2 和task1是同一个core处理的,所以task2的BlockA BlockB BlockC 写入了task1 的BlockA BlockB BlockC,由于同一个文件中是同一个下游task处理的,所以只要追加写入就可以了。

该优化方法,本质上是小文件的合并(同一个core的小文件数量合并),朝着这个方向,我们可以继续优化成“同一个executor(jvm)产生的同一个下游task的小文件合并”,和同一台机器合并,不过spark并没有实现这些优化。

由于同一个stage里的map的task不分先后顺序,但是同一个core里的task是先后处理的。所以同一个jvm或者同一台机器的小文件合并,没有同一个core的合并那么简单。

spark也提出过内存共享的优化方法,跨executor(jvm)去共享一台机器上面的内存。

该优化最终将小文件数量下降了X倍,X为平均每个core处理的task数量,

  • 比如,有100个map,下游是500个reduce,那原本是100*500=5w的小文件数量,现在map端分配的core是20个(每个core处理5个task),就变成了20*500=1w,缩小了5倍。

该优化方法虽然好,但是受限于机器并行的能力,如果机器并行的能力强,分配的core数量接近于map的数量,该优化就十分有限。

二、sortshuffle

为了实现更进一步的小文件合并,spark在随后提出了sortshuffle。

sortshuffle的目的,还是实现"更宽"的“共享”。

上述讲到hashshuffle对spark的小文件做了同一个core的合并,但是由于不同core的task没有先后顺序,很难合并。sortshuffle就是为了实现“每台机器上的map task小文件都合并”。

因为一台机器上的task之间执行没有顺序,所以要等待所有的task执行完成。无法有效利用并发能力。

如果按照之前的做法,为每个reduce task创建一个文件,并且同一台机器上的同一个reduce task的文件合并的话,这样最多能节省的倍数为平均一台机器处理的task数量,

  • 比如,有100个map,下游是500个reduce,那原本是100*500=5w的小文件数量,现在map端分配的core是20个,20个core在5台机器上(机器是4核的),就变成了5*500=2000,缩小了20倍。

显然优化者不满足于这种程度的优化,于是优化者这次对"*500" 动手了(reduce task的数量)。如何优化"*500", 原来一个map task 会产生500个task,现在将这些都合并了。所以就没有了"*500"

  • 比如,有100个map,下游是500个reduce,那原本是100*500=5w的小文件数量,现在合并了同一个map task产生的reduce task,那么文件数量就变成了100个。虽小了500倍,(由于要增加索引文件,所以实际上要除以2,是250倍)

只不过如果一个map,为500个reduce task 产生一个文件,这500个reduce task要怎么使用呢?答案是排序+索引,这就是sortshuffle的由来。

为了实现500个reduce task对一个文件的高效操作,map write的文件内部是有序的,并且还为该文件提供了一个索引文件。这样reduce task 就可以根据索引文件在该文件中找到自己对应的数据了。

该方式的map write的方式也发生了改变,类似于lsm的操作那样,每次内存写满了就一次性把内存数据进行排序,写入到磁盘生成一个文件,等到所有的数据都写入磁盘后,再对所有生成的文件进行一个归并排序。

这种shuffle的好处是大大减少了小文件的数量,且优化的力度不受限于reduce task的数量,只受限于map的数量。坏处是增加了一个排序的开销。

既然map write产生的文件都是有序的,为什么不再对同一台机器或core的的文件进行归并呢。答案是没有必要,太多的小文件会增大网络IO的开销,太少的文件对降低并发的利用率。不过,如果上游的数据量很大(map数量很多),而该key的基数(去重后的数量)比较小的话,还是可以考虑按core或jvm或机器级别进行合并的(合并还要考虑到索引的合并),不过spark没有提供这类优化。

三、bypass

bypass是sortshuffle的一种优化。上述提到,map write的文件内部做了全局排序。是为了多个reduce task能找到各自需要read的数据。但是在一个reduce task内,数据并不需要有序,而reduce task的数量一般远远小于数据行数(数据key的基数),所以这就造成了计算的浪费。

为了停止这种浪费,spark提出了新的shuffle优化bypass,即改变map write的方式,在write的时候,原来要对每一个flush到磁盘的小文件进行排序,现在不排序了,复制之前hashshuffle的做法,为每个reduce task写一个小文件。最后,将这些同一个map产生的小文件合并成一个大文件,合并的方式很简单,就直接追加就可以了,最后对结果文件增加一个索引,这样下游每一个reduce task都能找到自己要读的数据。这样既省下了排序的开销,又将小文件数量缩小到了2*M的数量(和sortshuffle一样)。可谓是兼具了hashshuffle和sortshuffle的优点。

不过该方法也有限制的地方。该shuffle不支持预聚合,map的数量也尽量要小(和最初的hashshuffle一样,map数量过大会产生过多的临时文件)

触发bypass的map数量上限可以用参数 spark.shuffle.sort.bypassMergeThreshold 设置

spark_shuffle方式的演进过程的更多相关文章

  1. P9架构师讲解从单机至亿级流量大型网站系统架构的演进过程

    阶段一.单机构建网站 网站的初期,我们经常会在单机上跑我们所有的程序和软件.此时我们使用一个容器,如tomcat.jetty.jboos,然后直接使用JSP/servlet技术,或者使用一些开源的框架 ...

  2. 阿里P9架构师讲解从单机至亿级流量大型网站系统架构的演进过程

    阶段一.单机构建网站 网站的初期,我们经常会在单机上跑我们所有的程序和软件.此时我们使用一个容器,如tomcat.jetty.jboos,然后直接使用JSP/servlet技术,或者使用一些开源的框架 ...

  3. Spring-cloud微服务实战【一】:微服务的概念与演进过程

    本文是一个系列文章,主要讲述使用spring-cloud进行微服务开发的实战.在开始之前,我们先说一下从传统的单一部署架构到微服务的发展过程,以便让童鞋们更好的理解微服务的概念与演进过程. 1.单体架 ...

  4. RPC 是通信协议吗 ?→ 我们来看下它的演进过程

    开心一刻 一实习小护士给我挂针,拿着针在我胳膊上扎了好几针也没找到血管 但这位小姑娘真镇定啊,表情严肃认真,势有不扎到血管不罢休的意思 十几针之后,我忍着剧痛,带着敬畏的表情问小护士:你这针法跟容嬷嬷 ...

  5. 框架源码系列四:手写Spring-配置(为什么要提供配置的方法、选择什么样的配置方式、配置方式的工作过程是怎样的、分步骤一个一个的去分析和设计)

    一.为什么要提供配置的方法 经过前面的手写Spring IOC.手写Spring DI.手写Spring AOP,我们知道要创建一个bean对象,需要用户先定义好bean,然后注册到bean工厂才能创 ...

  6. 图解 Kafka 超高并发网络架构演进过程

    阅读本文大约需要 30 分钟. 大家好,我是 华仔, 又跟大家见面了. 上一篇作为专题系列的第一篇,我们深度剖析了关于 Kafka 存储架构设计的实现细节,今天开启第二篇,我们来深度剖析下「Kafka ...

  7. Java的类演进过程

    1.从面向过程到面向对象 在大家最熟悉的C语言中,如果要定义一个复杂的数据类型就用结构体(Struct)来实现,而为结构体的每个操作都定义一个函数,这个函数与结构体本身的定义没有任何关系.程序的重心集 ...

  8. WINDOWS硬件通知应用程序的常方法(五种方式:异步过程调用APC,事件方式VxD,消息方式,异步I/O方式,事件方式WDM)

    摘要:在目前流行的Windows操作系统中,设备驱动程序是操纵硬件的最底层软件接口.为了共享在设备驱动程序设计过程中的经验,给出设备驱动程序通知应用程序的5种方法,详细说明每种方法的原理和实现过程,并 ...

  9. 浏览器打开URL的方式和加载过程

    不同浏览器的工作方式不完全一样,大体上,浏览器的核心是浏览器引擎,目前市场占有率最高的几种浏览器几乎都使用了不同的浏览器引擎:IE使用的是Trident.Firefox使用的是Gecko.Safari ...

随机推荐

  1. ssh+scp基本使用

    1 ssh ssh一般用于连接服务器,可以使用密码认证与密钥认证的方式. 1.1 密码认证 直接使用ssh即可: ssh username@xxx.xxx.xxx.xxx username为用户名,后 ...

  2. 我与Git的那些破事(上)--代码管理

    1. Git是什么? 作为一名程序猿,我相信大家都或多或少接触过git--分布式版本控制软件. 有人说,它是目前世界上最先进的分布式版本控制系统,我想说,是否最先进不知道,但确实好用,实用. 作为一款 ...

  3. 小程序picker地区级联选择的问题及解决方案

    各种系统中行政区域选择的场景不少,我们也有不少这样的场景.本想使用第三方的组件,但是大多有些小问题,不能满足需要.后面使用picker的mulitSelector模式写了一个,发现这种列模式的体验并好 ...

  4. 同事写了一个疯狂的类构造器,我要疯了,Builder 模式都不会么?!

    疯狂的类构造器 最近栈长在做 Code Review 时,发现一段创建对象的方法: Task task = new Task(112, "紧急任务", "处理一下这个任务 ...

  5. openpyxl 库

    1. 简介与安装 2.具体示例 2.1 获取workbook与sheet对象 2.2 访问单元格及其值 2.3 写数据 2.4 设置样式 1. 简介与安装 openpyxl 简介 openpyxl 是 ...

  6. 【原创】【基础】一文搞懂严蔚敏数据结构SqList &L和SqList L、ElemType &e和ElemType e

    旁白 最近小渔夫在看严蔚敏.李冬梅<数据结构 c语言版>(第2版),学到第二章顺序表的实现时,看到函数参数一会是SqList &L.一会又是SqList L.一会ElemType ...

  7. 【秒懂音视频开发】18_详解YUV

    本文的主角是多媒体领域非常重要的一个概念:YUV. 简介 YUV,是一种颜色编码方法,跟RGB是同一个级别的概念,广泛应用于多媒体领域中. 也就是说,图像中每1个像素的颜色信息,除了可以用RGB的方式 ...

  8. 利用主机域名配置Apache的虚拟主机功能

    利用主机域名配置Apache的虚拟主机功能,可以减轻服务器为每一个网站分配IP地址的压力.而且根据不同的主机域名可以输出不同的网页内容.要实现此项功能,可以通过修改/etc/host文件来强制定义IP ...

  9. Linux下逻辑卷LVM的管理和RAID磁盘阵列

    目录 LVM 一:LVM的创建 二:LVM的拉伸 三:LVM的缩小 四:LVM的删除 五:RAID磁盘阵列的添加 LVM LVM(Logical Volume Manager) 逻辑卷管理器,可以动态 ...

  10. layui中的多图上传

    效果展示: 1.html部分: 注:<input> 作为隐藏域,用于保存多图上传的资源数组,方便后期进行 form 表单的提交 <input type="hidden&qu ...