问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

MapReduce 为何一定要排序

创作时间:
作者:
@小白创作中心

MapReduce 为何一定要排序

引用
CSDN
1.
https://m.blog.csdn.net/m0_59236433/article/details/144156984

MapReduce是一种经典的分布式计算框架,广泛应用于大数据处理领域。其核心机制包括Map和Reduce两个阶段,通过简单的Key-Value数据格式实现复杂的计算任务。本文将深入探讨MapReduce中的排序机制,解释为什么排序对于提高数据处理效率至关重要。

MapReduce 机制

MapReduce 是一个非常经典的计算框架。

从数据格式的角度来说,仅仅用 Key-Value 这样简单的格式,就可以覆盖几乎所有的计算,大道至简。

从分布式计算的角度来说,抽象了 Map 和 Reduce 过程,把单机计算变成多节点的分布式计算,由此打开了大数据计算的大门。

经典的框架值得反复研究,Spark 一开始也想标新立异,抛弃MapReduce的一些实现,结果在不断的优化中仍然和 MapReduce 的理念非常像。

所以,在谷歌发布 MapReduce 论文的20年后,我们站在巨人的肩膀上来回忆一下 MapReduce 的设计理念。

MapReduce 是一种计算引擎,也是一种编程模型。MapReduce 提供了两个编程接口,即 Map 和 Reduce,让用户能够在此基础上编写自己的业务代码,而不用关心整个分布式计算框架的背后工作。

如下图所示为 MapReduce 运行所需要经过的环节。

以上五个环节还可以进一步分解成如图 5.2 所示的形式

以上过程分步骤描述一下:

  1. 创建 Split。由于 Map 任务最终是分布式的进程运行在不同的机器上,split 描述了每个 Map 任务该去哪台机器上的整块数据中,读取哪一部分的数据;

  2. 读取数据;

  3. 数据经过用户编写的 Map 业务处理,输入的是 Key-Value 格式,输出也是 Key-Value 格式。这一步其实是对数据标记的过程,为每条数据标记一个特征(key),相同特征的数据最终会到一起;

  4. 数据经过分区后,写入到内存缓冲区中;

  5. 内存缓冲区被写满 80%后,在内存中进行排序(先按照分区排序,每个分区内部按照 key 排序);

  6. 如果定义了 combiner 的话,进行一次合并;

  7. 每个 Map 溢写出一个文件出来;

  8. 最终对每个 Map 溢写出的文件合并成一个大文件;

  9. 进行一次 combine,写入到本地文件中;

  10. 进行到 reduce 阶段,每个 reduce 任务从上游数据中拷贝出属于自己的文件

  11. 调用用户定义的 reduce 方法进行计算;

  12. 最终结果写入到 hdfs 中

MapReduce 的排序

Map 端在对一个大文件进行计算的时候,首先要计算切片,每个切片分配一个 Map 任务。

这个 Map 任务计算之后,经过一个 partition 分区器,不同的 key 分配到不同的分区中。分区数量由下游的 reduce 数来决定。

经过分区后的数据,进入到一个环形缓冲区中,并且多次溢写之后,生成小文件。每个 Map Task 最终合并成一个文件。

如下图所示:

可以看到 merge 最后的一个文件中是分段的,第一段的数据是给下游的第一个reduce任务的,第二段的数据是给下游的第二个 reduce 的。

也就是下游的 每个 reduce 要来上游的每个 Map 任务的文件中,取到属于自己的那一段文件。

reduce 任务拉取完上游的各个分段数据之后,进行一次合并,合并到同一个文件中。

reduceTask 读取这个合并好的文件,把相同的key分组一次,进行计算即可。

现在问题就在这,如果 reduce 端合并之后的文件是乱序的,如下面这样:

a,1

c,1

a,1

b,1

....

那么reduce任务,如果要读取所有a的数据,就需要把整个文件从头到尾扫描一次,才能获取到所有a的数据。

如果有很多的 key,就得扫描多少次文件,肯定不是 MapReduce 引擎想要达到的效果。

那么如何读取文件一次,就可以把所有的 key 分组聚合好呢?

答案是:只要这个文件是有序的即可。

比如文件内容如下所示:

a,1

a,2

a,1

b,2

b,1

c,1

只要从上往下读取,只要读取到一个 key ,和上一个 key 不一样的时候,表示 a 都读取完了。

这样只要读取文件一次,就可以把各个 key 的特征汇总起来,就可以调用 reduce 的逻辑继续处理了。

既然 Reduce 端的输入需要 文件是有序的,而 reduce 阶段的文件是来自上游每个 map 的,只需要在上游环形缓冲区溢写之前,在内存中做一次快速排序,再溢写即可。

reduce 端拿到每段属于自己的数据之后,做一次归并排序,就可以很高效率的完成对整个文件的排序了。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号