分布式MapReduce原理详解

本文详细解析了MapReduce的工作原理,包括Map、Shuffle和Reduce三个主要阶段。Map阶段,数据按照字节切割,map任务处理数据并分区排序;Shuffle阶段,数据在内存中排序后溢写到磁盘,再进行合并排序;Reduce阶段,合并排序后的数据通过网络传输到reduce节点,执行reduce任务,最终写入HDFS。MapReduce通过并行化处理大量数据,实现了高效的分布式计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

MapReduce原理

一、什么是MapReduce?

       MapReduce是一个基于 java 的并行分布式计算框架,使用它来编写的数据处理应用可以运行在大型的商用硬件集群上来处理大型数据集中的可并行化问题,数据处理可以发生在存储在文件系统(非结构化)或数据库(结构化)中的数据上。MapReduce 可以利用数据的位置,在存储的位置附近处理数据,以最大限度地减少通信开销。
        框架通过编组分布式服务器,并行运行各种任务,管理系统各部分之间的所有通信和数据传输;其还能自动完成计算任务的并行化处理,自动划分计算数据和计算任务,在集群节点上自动分配和执行任务以及收集计算结果,将数据分布存储、数据通信、容错处理等并行计算涉及到的很多系统底层的复杂细节交由系统负责处理,减少开发人员的负担。

MapReduce框架通常由三个操作(或步骤)组成:

  1. Map:每个工作节点将map 函数应用于本地数据,并将输出写入临时存储。主节点确保仅处理冗余输入数据的一个副本。
  2. Shuffle:工作节点根据输出键(由 map 函数生成)重新分配数据,对数据映射排序、分组、拷贝,目的是属于一个键的所有数据都位于同一个工作节点上。
  3. Reduce:工作节点现在并行处理每个键的每组输出数据。

MapReduce

map任务处理

首先HDFS block块按照字节来切割,
block=split切片=map task(split比block大几KB或小几kb,因为切割时候按照字节来切,可能会将完整的字符串切割在不同block块)

1. shufflewriter
  1. 读取HDFS中的文件。每一行解析成一个<k,v>。每一个键值对调用一次map函数。
  2. 覆盖map(),接收1.1产生的<k,v>,进行处理,转换为新的<k,v>输出。
  3. 处理所有相关的键值对,然后将map task处理后的数据进行分区,分区的目的就是为了让这一条知道将来被哪一个reduce task处理,分区是由分区器进行的,默认的分区器是HashPartitioner,分区的策略是根据key的HashCode与reduce task NUM 取模(第一次排序)
  4. 进行buffer之后的每一条记录是由三部分组成(分区号,key,value)
    map task一条一条的往buffer中去写数据,一旦写入到80mb,此时他会将这80m的内存封锁,封锁后会对内存中的数据进行combiner(小聚合),对不同分区中的数据进行排序(按照k,分区号)、分组。将相同分区的数据放在一起,并且分区内的数据是有序的。(第二次排序)
  5. 以上的combiner以及排序完成后就开始溢写数据到磁盘上,此时的磁盘文件就是一个根据分区号分好区的,并且内部是有序的文件,每进行一次溢写就会产生一个磁盘小文件。combiner——>sort——>spill
  6. map task 计算完毕后,会将磁盘上的小文件合并成一个大文件,在合并的是偶会使用归并排序的算法,将各个小文件合并成一个有序的大文件(第三次排序)
    每一个map task都会经过以上所说所有一切,也就是每一个map task都会产生一个有分区的并且分区内部有序的大文件
2. shuffle read
  1. 去map端读取相应的分区数据,将分区数据写入到内存中,内存满了就会溢写,溢写之前会排序,当把所有数据取过来后,会将溢写产生的磁盘小文件合并 然后排序。形成有序的大文件(第四次排序)
    为什么要产生一个有序的大文件?
    就是为了提高分组的分组效率,四次排序都是为了提高分组效率

Reduce任务处理

  1. 多个map任务的输出,按照不同的分区,通过网络copy到不同的reduce节点上。
  2. 对多个map的输出进行合并、排序。覆盖reduce函数,接收的是分组后的数据,实现自己的业务逻辑,处理后,产生新的<k,v>输出。
  3. 对reduce输出的<k,v>写到HDFS中。

相关技术点

  • map task
  •         在进行map计算之前,mapreduce会根据输入文件计算输入分片(input split),每个输入分片(input split)针对一个map任务,输入分片(input split)存储的并非数据本身,而是一个分片长度和一个记录数据的位置的数组。
    Hadoop 2.x默认的block大小是128MB,Hadoop 1.x默认的block大小是64MB,可以在hdfs-site.xml中设置dfs.block.size,注意单位是byte。

  • Partition
  •         Partition是分割map每个节点的结果,按照key分别映射给不同的reduce,也是可以自定义的。这里其实可以理解归类。Partitioner接口可以根据key或value、以及reduce的数量来决定当前的map输出结果由哪个reduce处理。(默认方式是,计算key的哈希值,再对reduce数量取模。比如,计算得到的值是0,则指定第一个reduce处理)

  • combine
  •         combine分为map端和reduce端,作用是把同一个key的键值对合并在一起,可以自定义的。
    combine函数把一个map函数产生的<key,value>对(多个key,value)合并成一个新的<key2,value2>.将新的<key2,value2>作为输入到reduce函数中

  • Spill
  •         map输出时使用的内存缓冲区有大小限制,默认是100MB。当输出结果很多时,内存就会被填满,因此需要将缓冲区的数据写入磁盘,然后重新使用这块缓冲区。这个从内存往磁盘写数据的过程被称为Spill(溢出写)。
            map溢出写由单独一个线程负责,不影响往缓冲区写map结果的线程。所以在溢出写的过程中,map输出结果会继续被写入内存。当缓冲区的数据达到阈值(默认是80%,由属性 io.sort.spill.percent 设定),溢出写线程启动,对这80%的内存进行溢出写操作。
    在溢出写把map结果写到磁盘之前,需要进行两个重要的操作:sort(排序)和combine(合并)。
            msort是把这80%的map结果按照key排序。
            另外,因为一个map的输出结果会由不同的reduce处理(不同的key通过partition操作计算出来的值不同),所以要将属于同一个reduce处理的输出结果进行combine操作。

  • Merge
    每次溢出写都会在磁盘上生成一个溢出写文件,如果map输出结果很大,那么将会生成多个溢出写文件。(当map任务完成时,会把内存缓冲区中最后的结果也写到一个溢出写文件中)。为了方便后续阶段reduce来获取输出结果,这些溢出写文件将会被合并成一个文件,这就是merge操作。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值