透过生活看实质,源码解析分布式计算框架MapReduce(附源码)

目录

思想引入

MapReduce处理流程

MapReduce 具体分为四步:

MapReduce中的几个名词:

MapReduce执行流程:

map task 线程

1.1 map阶段

1.2 shuffle write阶段

reduce task 线程

2.1 shuffle read阶段

2.2 reduce阶段

MapReduce概述

MapReduce的定义

MapReduce的优缺点

最后指定是奉上代码啊--通过mapreduce编写wordcount


​思想引入

假设有1T的文件, 文件中的每一行都是一个数字; 如何在一台48core, 64G内存的服务器上处理这个大文件, 将这个大文件排序呢?

 

假设有两个很大的文件(内存只能读入一小部分), 文件中的每一行都是一个url字符串, 共有10亿行. 如何在一台48core, 64G内存的服务器上处理这两个大文件, 将这两个大文件中相同的url找出呢?

 

在一座山上有三个山头, 每个山头都有红木, 橡木和樟木, 有三个工人分别负责在一个山头砍树, 砍好的树木由三辆分别运送红木, 橡木和樟木的运输车运送到位于其他地方的三家加工厂, 这三家加工厂分别加工红木, 橡木和樟木. 整个处理流程应该是怎样的?

 

  1. 对于第一个问题, 这个1T的文件是无法完全读入内存中, 那么我们应该怎么做呢? 可以想到的是, 将这个大文件按行从上而下分割成一个个小文件分别读入服务器内存中处理, 服务器对每一个小文件进行排序, 最后再将每个内部有序的小文件进行归并排序, 从而产生一个有序文件.

 

  整个过程的流程图如下:

 

  虽然上述流程能够完成需求, 但是它存在一个问题----三次磁盘IO(第一次是切割文件时需要读写一次, 第二次是服务器排序时读写一下, 第三次是在归并排序时读写一次). 像这种磁盘IO是非常耗时的, 从而使得处理效率降低. 有什么地方可以改善吗?

 

  答案是有的. 关键就在于第一次怎么切割, 第一次切割时, 去限定每个小文件的数值范围, 比如说第一个小文件的数值范围是0~100, 第二个是101~200, 以此类推. 这样当服务器对每个小文件内部排好序时, 只需将这些小文件拼接即可.

 

  整个过程的流程图如下:

 

  上述流程相较于第一种减少一次IO(归并排序的IO), 从而提高处理的效率.

 

  2. 对于第二个问题, 还是要让整个过程只有两次磁盘IO. 首先要知道每一个字符串对应一个HashCode编码. 假设这两个文件都要拆成1000个小文件. 那么切割策略就有了: 先将每一个url的HashCode编码计算出来, 然后将这个值与1000取模, 每个" 模值 " 作为一个小文件的标识. 那么, 两个大文件中相同的url一定在模值相等的切割后的小文件中.

 

  整个过程的流程图如下:

 

  上述流程是一台服务器再处理, 假设现在有1000台服务器, 试想会是什么样情景呢?

 

  整个过程的流程图如下:

 

  上述流程的思想已经很接近MapReduce处理的思想.

 

  3. 对于第三个问题, 通常会认为伐木工砍完树之后, 将去掉树枝的树干运送到加工厂. 加工厂加工后还会剩下一批废料, 这些废料也占用了"运输通道", 对它们的传输是无用的, 因此也降低生成的效率, 那能否将这些无用的废料从"运输通道" 中除去呢?

 

  很简单, 只需要在山头那边对树木进行一定程度的加工不就可以了吗. 例如, 可以先分别加工出红木, 橡木和樟木的桌面, 桌腿再进行运输, 假设一次运输只能运送同一个组件, 那么这会造成运输次数的增加, 也降低了运输效率.

 

  既然如此, 桌面桌腿加工出来了, 再对它们进行简单组装形成半成品, 运输时直接输送半成品.

 

  可以看到, 我们在山头上对树干进行了两次加工, 分别产出桌面桌腿和桌子的半成品, 这一过程在MapReduce中称为Combiner. Combiner的过程减少了山头输出的数据, 类似于减少了网络IO

 

 

  上述第三个过程就跟MapReduce的过程类似了. MapReduce主要分两个过程Map和Reduce. 这里工人相当于Map; 每个山头上的组装称为combiner; 将半成品运输到各个工厂称为shuffle; 将运输过来的半成品组装成成品的过程称为reduce;

 

MapReduce处理流程

  官方配图:

 

MapReduce 具体分为四步:

 

Map 阶段;

Shuffle Write阶段

Shuffle Read阶段

Reduce 阶段

MapReduce中的几个名词:

 

map task – Map端开启的处理线程, 一个map task 读取的数据称为一个split(切片),

 

split – 切片的概念, 假设数据存放在HDFS上, 每一个map task读取的数据就是一个切片,但这并不是在读取前就切好的. split的默认大小与一个block的大小一致, 即block数 = split数 = map task数.

 也可设置split与block之间的大小关系, 例如, 2block = split = map task; 1/2block = split = map task.也可设置split与block之间的大小关系, 例如, 2block = split = map task; 1/2block = split = map task.

 split是一个逻辑概念, map task会一行一行的读取某个block中的数据, 为防止数据被切分, 它还会多读取下一个block的第一行数据(HDFS中按照字节存储数据, 所以极有可能一条数据被拆分存放在两个block中).

 

key-value : MR处理过程中, 数据都是通过键值对的形式传递的. 起初key值为block中一条记录的偏移量(long类型), value为block中的数据(String类型), 两个偏移量之间是一条记录. 经过map, reduce处理过后, key-value内容根据需求而定.

 

map – 对数据切分的方法, 输入类型为<LongWritable, Text>, 输出类型<key, value>由需求决定.

 

HashPartitioner – 默认分区器. 相同的分区由相同的reduce task处理,

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值