IT 论文精读 · PAPER 18

MapReduce:把「大规模并行」缩成两个函数

Jeffrey Dean & Sanjay Ghemawat · Google · OSDI 2004

EN →

这篇论文干了什么?

2004 年,Google 两位工程师公开了一套叫 MapReduce 的做法,专治一个头疼问题:有一大堆数据要算,一台机器算不完,得摊到上千台机器上一起算。问题是,「让一千台机器协同干一件活」本身极其难写——谁分到哪块数据、机器算到一半坏了怎么办、算完的碎片怎么拼回去……写这些琐事比写正经算法还累。MapReduce 的贡献是:把这些琐事一次性打包藏起来,只让你填两个空。它后来直接催生了开源的 Hadoop,开启了「大数据」这十几年。

先说说那个头疼的活儿

假设老板让你数一数:Google 爬回来的整个网页库里,每个单词各出现了多少次。逻辑简单到不能再简单——从头到尾扫一遍、见一个词就给它记一笔。可数据有几十 TB,一台机器扫到天荒地老。你只能拆给一千台机器分头数,最后再把一千份「小账本」合成一份大账本。真正折磨人的不是「数数」,而是「怎么把这件事安全地摊到一千台机器上」:怎么切、怎么分、哪台掉线了谁来补、结果怎么归拢——每写一个新的大数据任务,你都要把这套烂摊子重新收拾一遍。

它的点子:你只填两个空

MapReduce 说:这类活儿其实都能拆成同样的两步,你只要分别写清这两步,剩下的我全包。

第一步「Map(分头处理)」:告诉我,拿到一小片数据,你想吐出哪些「标签 → 数值」的小纸条。数单词就是:每见一个词,吐一张 (这个词, 1)第二步「Reduce(按标签归总)」:告诉我,把同一个标签的所有小纸条收到一起后,你想怎么把它们并成一个答案。数单词就是:把某个词收到的那一堆 1 加起来。你只写这两个「怎么做」,至于「谁去做、坏了怎么办、纸条怎么按标签归堆」——全是框架替你干的。

它凭什么又快又不怕坏

几个朴素但极管用的招。一、坏了就重算那一小块。框架有个「工头」盯着上千个「工人」,哪个工人算到一半没气了,工头把它那一小块活儿另派一个人重做即可,整个任务不用推倒重来——机器天天坏,也照跑不误。二、把活儿送到数据身边。数据本来就分散存在这些机器的硬盘上,框架尽量让「算某块数据的工人」正好就是「存着那块数据的机器」,省下海量网络搬运。三、专治「拖后腿的」。一千个工人里总有那么几个机器抽风、干得奇慢,拖着整个任务收不了尾;框架在快结束时会给这些慢活儿再找个人抢着做一遍,谁先干完算谁的——这一招能把总耗时砍掉一大截。

它带来了什么

MapReduce 把「写一个能在上千台机器上跑、还扛得住机器随时坏的大规模程序」这件从前只有分布式高手才敢碰的事,变成了普通工程师填两个函数就能做。Google 内部很快跑起成千上万个这样的任务,连它的搜索索引都用这套重写了一遍。开源世界照着它做出 Hadoop,几乎整个「大数据」行业都建在这个思路上。诚实的代价:它只擅长「从头到尾扫一大批数据」这种批量活儿,要你反复迭代、或要秒级实时响应,它就笨重了——后来的 Spark 等正是冲这点来的。

一句话记住

把「让上千台机器协同算一大堆数据」这件苦差,缩成你只需填的两个函数:Map(分头把数据变成「标签→数值」的小纸条)和 Reduce(按标签把纸条归总成答案)。谁去算、机器坏了怎么补、慢的怎么救、结果怎么拼——框架全包。这一下让普通人也能写大规模并行程序,开启了大数据时代。

想看它的执行流程图、容错与「抢跑救慢」机制、还有真实集群排序 1 TB 的数字? → 切到精读版