mapreduce和spark的工作机制及其shuffle的工作机制

3 篇文章 0 订阅
3 篇文章 0 订阅

一、mapreduce

1.工作机制

 


第一步,准备好文件;

第二步,切片分析;

第三步,客户端会提交3个信息:Job的切片、jar包(集群模式才有)、Job运行相关的参数信息;

第四步,Yarn会开启一个Mr appmaster(整个任务的老大),Mr appmaster会读取客户端提交的信息,根据切片信息开启对应个数的MapTask;

第五步,MapTask开启InputFormat(默认TextInputFormat)来按行读取对应切片内容,生成对应的kv(K是偏移量,V是每一行的内容),然后返回给Mapper;

第六步,读取数据后,调用jar中编写的mapper运行map函数,调用编写的运算逻辑;

第七步,数据被写入到环形缓冲区中;

(缓冲区中数据对<k,v>从右半边开始写入,索引从左半边开始写入;存储规则按照keystart---valstart---keystart---valstart...的形式;(keystart和valuestart之间指向的内容就是key数据,valuestart和keystart之间指向的内容就是value数据))

        环形缓冲区不需要重新申请新的内存,始终用的都是这个内存空间。MR是用java写的,而Java有一个最讨厌的机制就是Full GC。Full GC总是会出来捣乱,这个bug也非常隐蔽,发现了也不好处理。环形缓冲区从头到尾都在用那一个内存,不断重复利用,因此完美的规避了Full GC导致的各种问题,同时也规避了频繁申请内存引发的其他问题。

第八步中,排序方法是快排,排序指的是在溢写前排序,而不是写进去的时候就排序;排序针对的对象不是数据本身,而是数据对应的索引,而后按照字典的顺序排;(不同分区中的数据会被分配到不同的reduce任务中);分区数决定ReduceTask;
第九步,把排好序的内容溢写到磁盘文件中;
第十步,对溢写文件做归并排序(即图中左半部分和右半部分文件分别做归并排序);
第十一步,这一步不是一定发生的,这是一个预聚合的过程,即提前进行聚合然后再归并排序,相当于是特殊预聚合情况下的第十步;
第十二步,所有MapTask任务完成后,启动相应数量的ReduceTask(数目等于设定的分区数(不是绝对的,有可能先有一部分MapTask先进行了Reduce过程,可进行配置)(这一步可以不说明,直接说明Reducer任务会主动从Mapper任务复制其输出的键值对即可)
第十三步,ReduceTask拿到数据后进行合并,然后再进行一次归并排序(不同MapTask的同一分区数据放到一起做归并排序),这样后续就能很容易把相同key的内容发送到1个Reduce方法中;其中groupingComparator(可选)主要判断key值是否相同,决定数据是否会被划分为一组。如果有按照其规则判断;若不存在则必须内容完全相同则相同
第十四步,一次读取一组内容到Reduce方法中(也即key相同的一组数据);
第十五步,由OutputFormat向外写出数据;

2.shuffle工作机制

    map阶段之后,reduce之前的阶段称为shuffle。即mr工作原理的第七步到第十三步均是。

3.Hadoop优化

1)数据输入(小文件过多):

        合并小文件:在执行map前合并小文件

        采用CombineTextInputFormat作为输入

2)Map 阶段

  1. 增大环形缓冲区大小。由 100m 扩大到 200m
  2. 增大环形缓冲区溢写的比例。由 80%扩大到 90%
  3. 减少对溢写文件的 merge 次数。(10 个文件,一次 20 个 merge)
  4. 不影响实际业务的前提下,采用 Combiner 提前合并,减少I/O。

3)Reduce 阶段

  1. 合理设置 Map 和 Reduce 数:两个都不能设置太少,也不能设置太多。太少,会导致 Task 等待,延长处理时间;太多,会导致 Map、Reduce 任务间竞争资源,造成处理超时等错误。
  2. 设置 Map、Reduce 共存:调整 slowstart.completedmaps 参数,使 Map 运行到一定程度后,Reduce 也开始运行,减少 Reduce 的等待时间。
  3. 规避使用 Reduce,因为 Reduce 在用于连接数据集的时候将会产生大量的网络消耗。
  4. 增加每个 Reduce 去 Map 中拿数据的并行数
  5. 集群性能可以的前提下,增大 Reduce 端存储数据内存的大小。

4)IO 传输
采用数据压缩的方式,减少网络 IO 的的时间。安装 Snappy 和 LZOP 压缩编码器。
压缩:

  1. map 输入端主要考虑数据量大小和切片,支持切片的有 Bzip2、LZO。注意:LZO 要想支持切片必须创建索引;
  2. map 输出端主要考虑速度,速度快的 snappy、LZO;
  3. reduce 输出端主要看具体需求,例如作为下一个mr输入需要考虑切片,永久保存考虑压缩率比较大的 gzip。

5)其他

  1. (1)NodeManager 默认内存 8G,需要根据服务器实际配置灵活调整,例如 128G 内存,配置为100G 内存左右,yarn.nodemanager.resource.memory-mb。 
  2. (2)单任务默认内存 8G,需要根据该任务的数据量灵活调整,例如 128m 数据,配置 1G 内存,yarn.scheduler.maximum-allocation-mb。 
  3. (3)mapreduce.map.memory.mb :控制分配给MapTask 内存上限,如果超过会kill掉进程(报错:Container is running beyond physical memory limits. Current usage:565MB of512MBphysical memory used;Killing Container)。默认内存大小为 1G,如果数据量是 128m,正常不需要调整内存;如果数据量大于 128m,可以增加 MapTask 内存,最大可以增加到 4-5g。 
  4. (4)mapreduce.reduce.memory.mb:控制分配给ReduceTask内存上限。默认内存大小为1G,如果数据量是128m,正常不需要调整内存;如果数据量大于 128m,可以增加 ReduceTask 内存大小为 4-5g。 
  5. (5)mapreduce.map.java.opts:控制 MapTask 堆内存大小。(如果内存不够,报java.lang.OutOfMemoryError) 
  6. (6)mapreduce.reduce.java.opts:控制 ReduceTask 堆内存大小。(如果内存不够,报java.lang.OutOfMemoryError) 
  7. (7)可以增加 MapTask 的 CPU 核数,增加 ReduceTask 的 CPU 核数
  8. (8)增加每个 Container 的 CPU 核数和内存大小
  9. (9)在 hdfs-site.xml 文件中配置多目录(多磁盘)  
  10. (10)NameNode 有一个工作线程池,用来处理不同 DataNode 的并发心跳以及客户端并发的元数据操作。比如集群规模为 8 台时,此参数设置为 41。

 二、spark

shuffle

HashShuffle   

  1. Map Task将数据写入buffer缓冲区,待缓冲区达到阈值时开始溢写文件,文件数量取决于(等于)Reduce Task的数量。Reduce Task的数量取决于(等于)上一个Stage的最后一个RDD的分区数。
  2. Reduce Task一边拉取对应分区的数据到buffer缓存中,一边进行处理,使用map方法对数据进行归并,直至所有的数据归并结束。
  3. 每个map task都会为下游的每个reduce task创建一个磁盘文件(容易产生大量小文件,影响性能)

优化的HashShuffle

方法:设置consolidateFiles为true

  1. 一个executor为一个reduce task生成一个磁盘文件。
  2. consolidateFiles机制允许多个map task复用同一个磁盘文件,可以在一定程度上对map task的数据进行合并,从而大幅减小磁盘文件的数量,提升shuffle write性能。

SortShuffle(spark2.0后默认shuffle)

  1. map task会先将数据写入到一个数据结构中(reduceByKey写入Map,一边通过Map局部聚合,一边写入内存。Join算子写入ArrayList直接写入内存中。),当内存缓冲区中的数据达到一定阈值时,开始进行溢写。
  2. 溢写到磁盘之前,先按照数据的key进行排序,排序后分批次写入磁盘, 默认每批次1w条数据。
  3. 数据溢写到磁盘的过程中会产生多个临时磁盘文件,临时磁盘文件会进行merge归并,最终一个map task只会生成一个归并后的磁盘文件,同时还是生成一个对应的索引文件,记录数据的offset信息。
  4. reduce task拉取对应分区的数据进行处理。

bypass SortShuffle

满足条件:

  1. 不是聚合类型的shuffle算子
  2. map task的数量小于bypassMergeThreshold的值,默认是200。

优化:

  1. map task数据溢写到磁盘之前不会对数据进行排序。
  2. 数据的溢写规则和未经优化的hashshuffle一样,每个map task都会为下游的每个reduce task生成一个文件,但是最后会进行数据的归并,合并为一个磁盘文件。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MapReduceSpark都使用了Shuffle来进行数据的重新分区和排序。在MapReduce中,Shuffle是Map和Reduce之间的关键步骤,它负责将Map的输出按照键进行排序和分区,然后传递给Reduce进行处理。Shuffle的过程包括Map端的Shuffle和Reduce端的Shuffle。Map端的Shuffle主要是将Map的输出按照键进行排序和分区,然后写入磁盘。Reduce端的Shuffle则是从磁盘读取Map的输出,并按照键进行合并和排序,然后传递给Reduce进行处理。\[2\] 在Spark中,Shuffle也是对MapReduce Shuffle的优化。SparkShuffle分为两种实现方式,分别是HashShuffle和SortShuffle。HashShuffle使用哈希函数将数据分区到不同的节点上,然后在每个节点上进行本地排序。SortShuffle则是将数据按照键进行排序,然后再进行分区。SparkShuffle也包括Shuffle write和Shuffle read两个阶段,其中Shuffle write相当于MapReduce的map,负责将数据按照键进行排序和分区,然后写入磁盘;Shuffle read相当于MapReduce的reduce,负责从磁盘读取数据,并按照键进行合并和排序。\[1\]\[3\] 总结来说,MapReduceSparkShuffle都是用来重新分区和排序数据的关键步骤,但在实现上有一些不同。MapReduceShuffle是Map和Reduce之间的过程,而SparkShuffle是对MapReduce Shuffle的优化,并且有两种实现方式:HashShuffle和SortShuffle。 #### 引用[.reference_title] - *1* *2* *3* [详解MapReduce ShuffleSpark Shuffle](https://blog.csdn.net/u012369535/article/details/90757029)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值