shuffle | 青训营笔记

122 阅读3分钟

这是我参与「第四届青训营 」笔记创作活动的第2天 首先学习了shuffle的概念和shuffle的基本过程,然后学习了Spark中常用的shuffle算子,然后学习了shuffle过程,最后学习了push shuffle。 shuffle的运行过程:      在Mapper中的shuffle      1.当MapTask获取到Split之后按行读取数据      2.每读取一行调用一次map方法      3.每一行经过map方法处理以后,会产生一个或者多个key-value结果      4.Key-value的数据会暂时存到一个环形的缓冲区,这个缓冲区维系在内存中。      5.在缓冲区中会对数据进行分区-partition, 排序-sort, 合并-combine操作      6.当缓冲区使用在达到阈值(已使用缓冲区/缓冲区的总量,默认是0.8),将缓冲区的数据写到当前的磁盘中(spill—溢写),保存数据的格式—溢写。      7.对于单个溢写文件而言,里面的数据是分好区排好序的,但是对于整体所有的溢写文件而言是无序的。      8.等到所有的数据写完,会将所有的溢写文件进行一次合并(merge),合并到一个新的分区并且排序的文件中      9.再最终合并的时候,溢写文件个数<=3,那么合并完成之后会再执行一次Combinaer 在这个过程中需要注意的问题:   1. 当产生溢写的时候,缓冲区最后残留的数据会flush到最后一个溢写文件中   2.Spill理论上默认是80M,但是要考虑序列化以及最后的冲刷等因素   3.不能凭借一个MapTask处理的切片大小来衡量MapTask之后的输出数据的多少   4.每一个切片对应一个MapTask,每一个MapTask对应一个缓冲区   5.缓冲区本质上是一个字节数组   6.缓冲区又叫环形缓冲区,好处在于可以重复利用同一块地址的缓冲区   7.阈值的作用是避免Spill过程产生阻塞   8.merge过程可能不会发生 Reduce中的shuffle:   1.ReduceTask启动多个后台线程发起HTTP请求抓取数据----fetch      2.当前的ReduceTask值抓取对应分区的数据      3.RedcueTask从不同的MapTask上抓取了大量的数据,然后对这些数据进行merge(因为每个MapTask中合并的文件中有各个分区的数据)      4.在merge过程中,会对数据进行一次排序,保证当前分区中的数据有效(在这之后会进行一次分组过程)      5.Merge之后数据要进行一次分组(group),将相同的键所对应的值放到一个ArrayList      6.将ArrayList传递到Reducer中,Reducer将ArrayList转化为一个迭代器传到Reduce方法中      在Reduce中需要注意:   1.fetch的线程数量默认为5个   2.ReduceTask在启动的时候有一个阈值,这个阈值时表示有几个MapTask   3.执行完成之后就要启动ReduceTask,阈值默认时0.05(当有5%的mapTask执行完成之后,启动ReduceTack)   4.merge因子是10(默认十个合一个);

那么Shuffle调优就很重要的,主要有以下的方式: Reduce阶段:   1.增加fetch线程的数量   2.减小reduceTask的阈值—尽量不要动   3.调大merge因子 Mapper阶段:   1.调大缓冲区。建议在250—400M   2.指定combiner减少数据量   3.压缩数据以减少网络传输过程中的时间消耗(这种方式实际上是在网络和内存之间进行了取舍)