Spark的shuffle机制分析

一、shuffle概述

shuffle就是对数据进行重组,在MapReduce框架,shuffle是连接Map与Reduce之间的桥梁,Map阶段通过shuffle读取数据并输出到对应的Reduce而Reduce阶段负责从Map端拉取数据并进行计算。在整个shuffle过程中,往往伴随着大量的磁盘和网络I/O。所以shuffle性能的高低直接决定了整个程序的性能高低。

二、spark中的shuffle

在DAG(Directed Acyclic Graph)调度的过程中,Stage的划分依据是是否有shuffle过程,也就是宽依赖,这时候会将job划分为多个stage。

stage与stage之间的过程就是shuffle阶段,在Spark中,负责shuffle过程的执行、计算和处理的组件主要就是ShuffleManager,即shuffle管理器。ShuffleManager随着Spark 的发展有两种实现方式:HashShuffleManager和SortManager,因此Spark的shuffle有两种类型Hash Shuffle和Sort Shuffle。

三、HashShuffle机制

  • 概述:在Spark 1.2以前,默认的shuffle计算引擎是HashShuffleManager。但HashShuffleManager有一个严重的弊端就是会产生大量的中间磁盘文件,进而因为磁盘IO影响了性能。

  • Hash shuffle的普通机制

未优化的Shuffle原理图

  • shuffle write阶段
    • 在一个stage结束计算后,为了下一个stage可以执行shuffle类算子,将每个task处理的数据按key进行分区就是对key执行hash算法(分区器:hash/numreduce取模),将相同的key写入到同一个磁盘文件中,每一个磁盘文件都只属于reduce端的stage的一个task。在将数据写入磁盘之前,会先将数据写入内存缓冲,当内存缓冲填满之后,才会溢写到磁盘文件中去。
  • shuffle read阶段
    • 一个stage刚开始时,该stage的每一个task就需要将上一个stage的计算结果中所有相同的key,从各个节点上通过网络都拉取到自己所在的节点上,然后进行key的聚合或连接等操作。shuffle read的过程中,每个task只要从上游stage的所有task所在节点上,拉取属于自己的那一个磁盘文件即可。read的拉取是一边拉取一边聚合的,每个shuffle read task都有一个自己的buffer缓冲,默认为32K,每次只拉取与buffer缓冲相同大小的数据。
  • 普通机制存在的问题
    • Shuffle阶段在磁盘上会产生大量小文件**(task*reducenum)**,简历通信和拉取数据的次数变多,会产生大量耗时低效的IO操作。
    • 可能导致OOM,大量耗时低效的 IO 操作 ,导致写磁盘时的对象过多,读磁盘时候的对象也过多,这些对象存储在堆内存中,会导致堆内存不足,相应会导致频繁的GC,GC会导致OOM。由于内存中需要保存海量文件操作句柄和临时信息,如果数据处理的规模比较庞大的话,内存不可承受,会出现 OOM 等问题

优化后的shuffle机制

  • 合并机制的Hash shuffle
    在map端会生成cpu core * numreduce个文件,第一次并行执行的task,每个task创建numreduce个文件,再次执行map task 时会复用上一次产生的文件。启动合并机制的配置spark.shuffle.consolidateFiles=true
  • 合并机制存在的问题
    假如task并行度过大,或者分片过多的话还是会产生大量的小文件。

四、SortShuffle机制

  • SortShuffle的普通机制在这里插入图片描述
  • 该模式下,会将数据写入一个数据结构,聚合算子会写入一个Map,一边通过Map进行局部聚合,一边写入内存;join算子会写入一个ArrayList,直接写入内存。
  • 当内存数据达到5M后,就会将内存中的数据写到磁盘中,并清空数据结构
  • 在写到磁盘中之前,会先将数据根据key进行排序,排序后的数据会分批写入磁盘,通过缓冲区溢写的方式每1W条数据溢写一次,每次溢写都会产生一个临时文件,所以一个task会产生多个临时文件。
  • 最后在每个task中,将所有的临时文件合并,这就是merge过程,此过程将所有临时文件读取出来,一次写入到最终文件。意味着一个task的所有数据都在这一个文件中。同时单独写一份索引文件,标识下游各个task的数据在文件中的索引start offset和end offset。
  • 优点:
  1. 小文件明显变少了,一个task只生成一个file文件
  2. file文件整体有序,加上索引文件的辅助,查找变快,虽然排序浪费一些性能,但是查找变快很多
  • bypass模式的sortShuffle
    bypass机制运行条件
  • shuffle map task数量小于spark.shuffle.sort.bypassMergeThreshold参数的值默认值200
  • 不是聚合类的shuffle算子(比如reduceByKey)在这里插入图片描述
  • task会为每个下游task都创建一个临时磁盘文件,并将数据按key进行hash然后根据key的hash值,将key写入对应的磁盘文件之中。当然,写入磁盘文件时也是先写入内存缓冲,缓冲写满之后再溢写到磁盘文件的。最后,同样会将所有临时磁盘文件都合并成一个磁盘文件,并创建一个单独的索引文件。
  • 该机制与普通SortShuffleManager运行机制的不同在于:
    第一: 磁盘写机制不同;
    第二: 不会进行sort排序;
  • 该机制的磁盘写机制与未优化的HashShuffleManager是一样的,但最终做了一个合并,减少了最终文件,这使得SortShuffleManager在shuffle read方面更有优势。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值