昨天,我在Xebia印度办公室发表了一个关于MapReduce的演说。演说进行得很顺利,听众们都能够理解MapReduce的概念(根据他们的反馈)。我成功地向技术听众们(主要是Java程序员,一些Flex程序员和少数的测试人员)解释了MapReduce的概念,这让我感到兴奋。在所有辛勤的工作之后,我们在Xebia印度办公室享用了丰盛的晚餐,然后我径直回了家。

回家后,我的妻子(Supriya)问道:“你的会开得怎么样?”我说还不错。 接着她又问我会议是的内容是什么(她不是从事软件或编程领域的工作的)。我告诉她说MapReduce。“Mapduce,那是什么玩意儿?”她问道: “跟地形图有关吗?”我说不,不是的,它和地形图一点关系也没有。“那么,它到底是什么玩意儿?”妻子问道。 “唔…让我们去Dominos(披萨连锁)吧,我会在餐桌上跟你好好解释。” 妻子说:“好的。” 然后我们就去了披萨店。

我们在Domions点餐之后,柜台的小伙子告诉我们说披萨需要15分钟才能准备好。于是,我问妻子:“你真的想要弄懂什么是MapReduce?” 她很坚定的回答说“是的”。 因此我问道:

我: 你是如何准备洋葱辣椒酱的?(以下并非准确食谱,请勿在家尝试)

妻子: 我会取一个洋葱,把它切碎,然后拌入盐和水,最后放进混合研磨机里研磨。这样就能得到洋葱辣椒酱了。

妻子: 但这和MapReduce有什么关系?

我: 你等一下。让我来编一个完整的情节,这样你肯定可以在15分钟内弄懂MapReduce.

妻子: 好吧。

我:现在,假设你想用薄荷、洋葱、番茄、辣椒、大蒜弄一瓶混合辣椒酱。你会怎么做呢?

妻子: 我会取薄荷叶一撮,洋葱一个,番茄一个,辣椒一根,大蒜一根,切碎后加入适量的盐和水,再放入混合研磨机里研磨,这样你就可以得到一瓶混合辣椒酱了。

我: 没错,让我们把MapReduce的概念应用到食谱上。Map和Reduce其实是两种操作,我来给你详细讲解下。

Map(映射): 把洋葱、番茄、辣椒和大蒜切碎,是各自作用在这些物体上的一个Map操作。所以你给Map一个洋葱,Map就会把洋葱切碎。 同样的,你把辣椒,大蒜和番茄一一地拿给Map,你也会得到各种碎块。 所以,当你在切像洋葱这样的蔬菜时,你执行就是一个Map操作。 Map操作适用于每一种蔬菜,它会相应地生产出一种或多种碎块,在我们的例子中生产的是蔬菜块。在Map操作中可能会出现有个洋葱坏掉了的情况,你只要把坏洋葱丢了就行了。所以,如果出现坏洋葱了,Map操作就会过滤掉坏洋葱而不会生产出任何的坏洋葱块。

Reduce(化简):在这一阶段,你将各种蔬菜碎都放入研磨机里进行研磨,你就可以得到一瓶辣椒酱了。这意味要制成一瓶辣椒酱,你得研磨所有的原料。因此,研磨机通常将map操作的蔬菜碎聚集在了一起。

妻子: 所以,这就是MapReduce?

我: 你可以说是,也可以说不是。 其实这只是MapReduce的一部分,MapReduce的强大在于分布式计算。

妻子: 分布式计算? 那是什么?请给我解释下吧。

我: 没问题。

我: 假设你参加了一个辣椒酱比赛并且你的食谱赢得了最佳辣椒酱奖。得奖之后,辣椒酱食谱大受欢迎,于是你想要开始出售自制品牌的辣椒酱。假设你每天需要生产10000瓶辣椒酱,你会怎么办呢?

妻子: 我会找一个能为我大量提供原料的供应商。

我:是的..就是那样的。那你能否独自完成制作呢?也就是说,独自将原料都切碎? 仅仅一部研磨机又是否能满足需要?而且现在,我们还需要供应不同种类的辣椒酱,像洋葱辣椒酱、青椒辣椒酱、番茄辣椒酱等等。

妻子: 当然不能了,我会雇佣更多的工人来切蔬菜。我还需要更多的研磨机,这样我就可以更快地生产辣椒酱了。

我:没错,所以现在你就不得不分配工作了,你将需要几个人一起切蔬菜。每个人都要处理满满一袋的蔬菜,而每一个人都相当于在执行一个简单的Map操作。每一个人都将不断的从袋子里拿出蔬菜来,并且每次只对一种蔬菜进行处理,也就是将它们切碎,直到袋子空了为止。

这样,当所有的工人都切完以后,工作台(每个人工作的地方)上就有了洋葱块、番茄块、和蒜蓉等等。

妻子:但是我怎么会制造出不同种类的番茄酱呢?

我:现在你会看到MapReduce遗漏的阶段—搅拌阶段。MapReduce将所有输出的蔬菜碎都搅拌在了一起,这些蔬菜碎都是在以key为基础的 map操作下产生的。搅拌将自动完成,你可以假设key是一种原料的名字,就像洋葱一样。 所以全部的洋葱keys都会搅拌在一起,并转移到研磨洋葱的研磨器里。这样,你就能得到洋葱辣椒酱了。同样地,所有的番茄也会被转移到标记着番茄的研磨器里,并制造出番茄辣椒酱。

披萨终于做好了,她点点头说她已经弄懂什么是MapReduce了。我只希望下次她听到MapReduce时,能更好的理解我到底在做些什么。

编注:下面这段话是网上其他人用最简短的语言解释MapReduce:

We want to count all the books in the library. You count up shelf #1, I count up shelf #2. That’s map. The more people we get, the faster it goes.

我们要数图书馆中的所有书。你数1号书架,我数2号书架。这就是“Map”。我们人越多,数书就更快。

Now we get together and add our individual counts. That’s reduce.

现在我们到一起,把所有人的统计数加在一起。这就是“Reduce”。

简单解释 MapReduce 算法

一个有趣的例子

你想数出一摞牌中有多少张黑桃。直观方式是一张一张检查并且数出有多少张是黑桃?

MapReduce方法则是:

  1. 给在座的所有玩家中分配这摞牌
  2. 让每个玩家数自己手中的牌有几张是黑桃,然后把这个数目汇报给你
  3. 你把所有玩家告诉你的数字加起来,得到最后的结论

拆分

MapReduce合并了两种经典函数:

  • 映射(Mapping)对集合里的每个目标应用同一个操作。即,如果你想把表单里每个单元格乘以二,那么把这个函数单独地应用在每个单元格上的操作就属于mapping。
  • 化简(Reducing )遍历集合中的元素来返回一个综合的结果。即,输出表单里一列数字的和这个任务属于reducing。

重新审视上面的例子

重新审视我们原来那个分散纸牌的例子,我们有MapReduce数据分析的基本方法。友情提示:这不是个严谨的例子。在这个例子里,人代表计算机,因为他们同时工作,所以他们是个集群。在大多数实际应用中,我们假设数据已经在每台计算机上了 – 也就是说把牌分发出去并不是MapReduce的一步。(事实上,在计算机集群中如何存储文件是Hadoop的真正核心。)

通过把牌分给多个玩家并且让他们各自数数,你就在并行执行运算,因为每个玩家都在同时计数。这同时把这项工作变成了分布式的,因为多个不同的人在解决同一个问题的过程中并不需要知道他们的邻居在干什么。

通过告诉每个人去数数,你对一项检查每张牌的任务进行了映射。 你不会让他们把黑桃牌递给你,而是让他们把你想要的东西化简为一个数字。

另外一个有意思的情况是牌分配得有多均匀。MapReduce假设数据是洗过的(shuffled)- 如果所有黑桃都分到了一个人手上,那他数牌的过程可能比其他人要慢很多。

如果有足够的人的话,问一些更有趣的问题就相当简单了 – 比如“一摞牌的平均值(二十一点算法)是什么”。你可以通过合并“所有牌的值的和是什么”及“我们有多少张牌”这两个问题来得到答案。用这个和除以牌的张数就得到了平均值。

MapReduce算法的机制要远比这复杂得多,但是主体思想是一致的 – 通过分散计算来分析大量数据。无论是Facebook、NASA,还是小创业公司,MapReduce都是目前分析互联网级别数据的主流方法。

Hadoop中的MapReduce

大规模数据处理时,MapReduce在三个层面上的基本构思

如何对付大数据处理:分而治之

对相互间不具有计算依赖关系的大数据,实现并行最自然的办法就是采取分而治之的策略

上升到抽象模型:Mapper与Reducer

MPI等并行计算方法缺少高层并行编程模型,为了克服这一缺陷,MapReduce借鉴了Lisp函数式语言中的思想,用Map和Reduce两个函数提供了高层的并行编程抽象模型

上升到构架:统一构架,为程序员隐藏系统层细节

MPI等并行计算方法缺少统一的计算框架支持,程序员需要考虑数据存储、划分、分发、结果收集、错误恢复等诸多细节;为此,MapReduce设计并提供了统一的计算框架,为程序员隐藏了绝大多数系统层面的处理细节

1.对付大数据处理-分而治之

什么样的计算任务可进行并行化计算?

并行计算的第一个重要问题是如何划分计算任务或者计算数据以便对划分的子任务或数据块同时进行计算。但一些计算问题恰恰无法进行这样的划分!

Nine women cannot have a baby in one month!

例如:Fibonacci函数:  Fk+2 = Fk + Fk+1

前后数据项之间存在很强的依赖关系!只能串行计算!

结论:不可分拆的计算任务或相互间有依赖关系的数据无法进行并行计算!

大数据的并行化计算

一个大数据若可以分为具有同样计算过程的数据块,并且这些数据块之间不存在数据依赖关系,则提高处理速度的最好办法就是并行计算

例如:假设有一个巨大的2维数据需要处理(比如求每个元素的开立方),其中对每个元素的处理是相同的,并且数据元素间不存在数据依赖关系,可以考虑不同的划分方法将其划分为子数组,由一组处理器并行处理

2.构建抽象模型-Map和Reduce

借鉴函数式设计语言Lisp的设计思想

—函数式程序设计(functional programming)语言Lisp是一种列表处理 语言(List processing),是一种应用于人工智能处理的符号式语言,由MIT的人工智能专家、图灵奖获得者John McCarthy于1958年设计发明。

—Lisp定义了可对列表元素进行整体处理的各种操作,如:

如:(add #(1 2 3 4) #(4 3 2 1))   将产生结果: #(5 5 5 5)

—Lisp中也提供了类似于Map和Reduce的操作

如: (map ‘vector #+ #(1 2 3 4 5)  #(10 11 12 13 14))

通过定义加法map运算将2个向量相加产生结果#(11 13 15 17 19)

(reduce #’+ #(11  13  15  17  19)) 通过加法归并产生累加结果75

Map: 对一组数据元素进行某种重复式的处理

Reduce: 对Map的中间结果进行某种进一步的结果整

关键思想:为大数据处理过程中的两个主要处理操作提供一种抽象机制

MapReduce中的Map和Reduce操作的抽象描述

MapReduce借鉴了函数式程序设计语言Lisp中的思想,定义了如下的Map和Reduce两个抽象的编程接口,由用户去编程实现:

—map: (k1; v1) → [(k2; v2)]

输入:键值对(k1; v1)表示的数据

处理:文档数据记录(如文本文件中的行,或数据表格中的行)将以“键值对”形式传入map函数;map函数将处理这些键值对,并以另一种键值对形式输出处理的一组键值对中间结果   [(k2; v2)]

输出:键值对[(k2; v2)]表示的一组中间数据

—reduce: (k2; [v2]) → [(k3; v3)]

输入: 由map输出的一组键值对[(k2; v2)] 将被进行合并处理将同样主键下的不同数值合并到一个列表[v2]中,故reduce的输入为(k2; [v2])

处理:对传入的中间结果列表数据进行某种整理或进一步的处理,并产生最终的某种形式的结果输出[(k3; v3)] 。

输出:最终输出结果[(k3; v3)]

Map和Reduce为程序员提供了一个清晰的操作接口抽象描述

各个map函数对所划分的数据并行处理,从不同的输入数据产生不同的中间结果输出

—各个reduce也各自并行计算,各自负责处理不同的中间结果数据集合—进行reduce处理之前,必须等到所有的map函数做完,因此,在进入reduce前需要有一个同步障(barrier);这个阶段也负责对map的中间结果数据进行收集整理(aggregation & shuffle)处理,以便reduce更有效地计算最终结果—最终汇总所有reduce的输出结果即可获得最终结果

基于MapReduce的处理过程示例—文档词频统计:WordCount

设有4组原始文本数据:

Text 1: the weather is good         Text 2: today is good

Text 3: good weather is good      Text 4: today has good weather

传统的串行处理方式(Java):

String[] text = new String[] { “hello world”, “hello every one”, “say hello to everyone in the world” };
HashTable ht = new HashTable();
for(i = 0; i < 3; ++i) {StringTokenizer st = new StringTokenizer(text[i]); while (st.hasMoreTokens()) {  String word = st.nextToken();if(!ht.containsKey(word)) {  ht.put(word, new Integer(1));} else {int wc = ((Integer)ht.get(word)).intValue() +1;// 计数加1ht.put(word, new Integer(wc));}}
}
for (Iterator itr=ht.KeySet().iterator();  itr.hasNext(); ) {String word = (String)itr.next(); System.out.print(word+ “: ”+ (Integer)ht.get(word)+“;   ”);

输出:good:  5;   has: 1;  is: 3;   the: 1;   today: 2;    weather: 3

基于MapReduce的处理过程示例—文档词频统计:WordCount

MapReduce处理方式

使用4个map节点:

map节点1:

输入:(text1, “the weather is good”)

输出:(the, 1), (weather, 1), (is, 1), (good, 1)

map节点2:

输入:(text2, “today is good”)

输出:(today, 1), (is, 1), (good, 1)

map节点3:

输入:(text3, “good weather is good”)

输出:(good, 1), (weather, 1), (is, 1), (good, 1)

map节点4:

输入:(text3, “today has good weather”)

输出:(today, 1), (has, 1), (good, 1), (weather, 1)

使用3个reduce节点:

MapReduce处理方式

MapReduce伪代码(实现Map和Reduce两个函数):

C
ClassMappermethodmap(Stringinput_key,Stringinput_value):// input_key: text document name // input_value: document contents foreachwordwininput_value:EmitIntermediate(w,"1");ClassReducermethodreduce(Stringoutput_key,Iteratorintermediate_values):// output_key: a word // output_values: a list of counts intresult=0;foreachvinintermediate_values:result+=ParseInt(v);Emit(output_key,result);

3.上升到构架-自动并行化并隐藏低层细节

如何提供统一的计算框架

MapReduce提供一个统一的计算框架,可完成:

—计算任务的划分和调度

—数据的分布存储和划分

—处理数据与计算任务的同步

—结果数据的收集整理(sorting, combining, partitioning,…)

—系统通信、负载平衡、计算性能优化处理

—处理系统节点出错检测和失效恢复

MapReduce最大的亮点

—通过抽象模型和计算框架把需要做什么(what need to do)与具体怎么做(how to do)分开了,为程序员提供一个抽象和高层的编程接口和框架

—程序员仅需要关心其应用层的具体计算问题,仅需编写少量的处理应用本身计算问题的程序代码

—如何具体完成这个并行计算任务所相关的诸多系统层细节被隐藏起来,交给计算框架去处理:从分布代码的执行,到大到数千小到单个节点集群的自动调度使用

MapReduce提供的主要功能

—任务调度:提交的一个计算作业(job)将被划分为很多个计算任务(tasks), 任务调度功能主要负责为这些划分后的计算任务分配和调度计算节点(map节点或reducer节点); 同时负责监控这些节点的执行状态, 并负责map节点执行的同步控制(barrier); 也负责进行一些计算性能优化处理, 如对最慢的计算任务采用多备份执行、选最快完成者作为结果

—数据/代码互定位:为了减少数据通信,一个基本原则是本地化数据处理(locality),即一个计算节点尽可能处理其本地磁盘上所分布存储的数据,这实现了代码向数据的迁移;当无法进行这种本地化数据处理时,再寻找其它可用节点并将数据从网络上传送给该节点(数据向代码迁移),但将尽可能从数据所在的本地机架上寻找可用节点以减少通信延迟

—出错处理:以低端商用服务器构成的大规模MapReduce计算集群中,节点硬件(主机、磁盘、内存等)出错和软件有bug是常态,因此,MapReducer需要能检测并隔离出错节点,并调度分配新的节点接管出错节点的计算任务
—分布式数据存储与文件管理:海量数据处理需要一个良好的分布数据存储和文件管理系统支撑,该文件系统能够把海量数据分布存储在各个节点的本地磁盘上,但保持整个数据在逻辑上成为一个完整的数据文件;为了提供数据存储容错机制,该文件系统还要提供数据块的多备份存储管理能力
—Combiner和Partitioner:为了减少数据通信开销,中间结果数据进入reduce节点前需要进行合并(combine)处理,把具有同样主键的数据合并到一起避免重复传送; 一个reducer节点所处理的数据可能会来自多个map节点, 因此, map节点输出的中间结果需使用一定的策略进行适当的划分(partitioner)处理,保证相关数据发送到同一个reducer节点

基于Map和Reduce的并行计算模型

4.MapReduce的主要设计思想和特征

1、向“外”横向扩展,而非向“上”纵向扩展(Scale “out”, not “up”)

即MapReduce集群的构筑选用价格便宜、易于扩展的大量低端商用服务器,而非价格昂贵、不易扩展的高端服务器(SMP)—低端服务器市场与高容量Desktop PC有重叠的市场,因此,由于相互间价格的竞争、可互换的部件、和规模经济效应,使得低端服务器保持较低的价格—基于TPC-C在2007年底的性能评估结果,一个低端服务器平台与高端的共享存储器结构的服务器平台相比,其性价比大约要高4倍;如果把外存价格除外,低端服务器性价比大约提高12倍—对于大规模数据处理,由于有大量数据存储需要,显而易见,基于低端服务器的集群远比基于高端服务器的集群优越,这就是为什么MapReduce并行计算集群会基于低端服务器实现

2、失效被认为是常态(Assume failures are common)

MapReduce集群中使用大量的低端服务器(Google目前在全球共使用百万台以上的服务器节点),因此,节点硬件失效和软件出错是常态,因而:—一个良好设计、具有容错性的并行计算系统不能因为节点失效而影响计算服务的质量,任何节点失效都不应当导致结果的不一致或不确定性;任何一个节点失效时,其它节点要能够无缝接管失效节点的计算任务;当失效节点恢复后应能自动无缝加入集群,而不需要管理员人工进行系统配置—MapReduce并行计算软件框架使用了多种有效的机制,如节点自动重启技术,使集群和计算框架具有对付节点失效的健壮性,能有效处理失效节点的检测和恢复。

3、把处理向数据迁移(Moving processing to the data)

—  传统高性能计算系统通常有很多处理器节点与一些外存储器节点相连,如用区域存储网络(SAN,Storage Area Network)连接的磁盘阵列,因此,大规模数据处理时外存文件数据I/O访问会成为一个制约系统性能的瓶颈。—为了减少大规模数据并行计算系统中的数据通信开销,代之以把数据传送到处理节点(数据向处理器或代码迁移),应当考虑将处理向数据靠拢和迁移。—MapReduce采用了数据/代码互定位的技术方法,计算节点将首先将尽量负责计算其本地存储的数据,以发挥数据本地化特点(locality),仅当节点无法处理本地数据时,再采用就近原则寻找其它可用计算节点,并把数据传送到该可用计算节点。

4、顺序处理数据、避免随机访问数据(Process data sequentially and avoid random access)

— 大规模数据处理的特点决定了大量的数据记录不可能存放在内存、而只可能放在外存中进行处理。—磁盘的顺序访问和随即访问在性能上有巨大的差异

例:100亿(1010)个数据记录(每记录100B,共计1TB)的数据库

更新1%的记录(一定是随机访问)需要1个月时间;而顺序访问并重写所有数据记录仅需1天时间!

—MapReduce设计为面向大数据集批处理的并行计算系统,所有计算都被组织成很长的流式操作,以便能利用分布在集群中大量节点上磁盘集合的高传输带宽。

5、为应用开发者隐藏系统层细节(Hide system-level details from the application developer)

—  软件工程实践指南中,专业程序员认为之所以写程序困难,是因为程序员需要记住太多的编程细节(从变量名到复杂算法的边界情况处理),这对大脑记忆是一个巨大的认知负担,需要高度集中注意力—而并行程序编写有更多困难,如需要考虑多线程中诸如同步等复杂繁琐的细节,由于并发执行中的不可预测性,程序的调试查错也十分困难;大规模数据处理时程序员需要考虑诸如数据分布存储管理、数据分发、数据通信和同步、计算结果收集等诸多细节问题—MapReduce提供了一种抽象机制将程序员与系统层细节隔离开来,程序员仅需描述需要计算什么(what to compute), 而具体怎么去做(how to compute)就交由系统的执行框架处理,这样程序员可从系统层细节中解放出来,而致力于其应用本身计算问题的算法设计

6、平滑无缝的可扩展性(Seamless scalability)

主要包括两层意义上的扩展性:数据扩展和系统规模扩展。—理想的软件算法应当能随着数据规模的扩大而表现出持续的有效性,性能上的下降程度应与数据规模扩大的倍数相当—在集群规模上,要求算法的计算性能应能随着节点数的增加保持接近线性程度的增长—绝大多数现有的单机算法都达不到以上理想的要求;把中间结果数据维护在内存中的单机算法在大规模数据处理时很快失效;从单机到基于大规模集群的并行计算从根本上需要完全不同的算法设计—奇妙的是,MapReduce几乎能实现以上理想的扩展性特征。  多项研究发现基于MapReduce的计算性能可随节点数目增长保持近似于线性的增长

参考资料:

http://blog.jobbole.com/1321/

http://blog.jobbole.com/80619/

http://blog.csdn.net/lifuxiangcaohui/article/details/22675437

http://www.cnblogs.com/yangsy0915/p/5559969.html(Hadoop 2.6 MapReduce运行原理详解)

Hadoop系列-MapReduce设计思想与原理机制(九)相关推荐

  1. 搞一下 AP AUTOSAR 原理及实战 | 01 AP AUTOSAR 设计思想及原理

    前言 搞SOA.搞 AP & CP AUTOSAR.搞异构SoC.搞车载以太网.搞车载OS等就找搞一下汽车电子. 全系内容可在<搞一下汽车电子>后台回复 "系列" ...

  2. hadoop之MapReduce框架TaskTracker端心跳机制分析(源码分析第六篇)

    1.概述 MapReduce框架中的master/slave心跳机制是整个集群运作的基础,是沟通TaskTracker和JobTracker的桥梁.TaskTracker周期性地调用心跳RPC函数,汇 ...

  3. [Hadoop入门] - 1 Ubuntu系统 Hadoop介绍 MapReduce编程思想

    Ubuntu系统 (我用到版本号是140.4) ubuntu系统是一个以桌面应用为主的Linux操作系统,Ubuntu基于Debian发行版和GNOME桌面环境.Ubuntu的目标在于为一般用户提供一 ...

  4. 《Spring设计思想》AOP设计思想与原理(图文并茂)

    Spring 提供了AOP(Aspect Oriented Programming) 的支持, 那么,什么是AOP呢?本文将通过一个另外一个角度来诠释AOP的概念,帮助你更好地理解和使用Spring ...

  5. 3.Kafka系列之设计思想(一)

    最近在看官方文档,第4章DESIGN内容我觉得挺好,分享给大家 4.1 Motivation动机 We designed Kafka to be able to act as a unified pl ...

  6. 自顶向下语法分析原理与设计思想

    这里重在讲解设计思想和原理,由于时间久远,一些知识的记忆不太清晰,若有不当之处,请多多指出. 编译原理中的自顶向下语法分析的算法步骤有点麻烦,但是原理与设计思想,及其简单,甚至于没有技术含量. 首先解 ...

  7. Hadoop技术内幕:深入解析MapReduce架构设计与实现原理 (大数据技术丛书) - 电子书下载(高清版PDF格式+EPUB格式)...

    Hadoop技术内幕:深入解析MapReduce架构设计与实现原理 (大数据技术丛书)-董西成著 在线阅读                   百度网盘下载(ihhy) 书名:Hadoop技术内幕:深 ...

  8. Hadoop技术内幕:深入解析MapReduce架构设计与实现原理

    <Hadoop技术内幕:深入解析MapReduce架构设计与实现原理> 基本信息 作者: 董西成 丛书名: 大数据技术丛书 出版社:机械工业出版社 ISBN:9787111422266 上 ...

  9. MapReduce原理与设计思想

    转自:http://www.cnblogs.com/archimedes/p/mapreduce-principle.html 简单解释 MapReduce 算法 一个有趣的例子 你想数出一摞牌中有多 ...

  10. MapReduce原理与设计思想(转载:http://blog.jobbole.com/80619/)

    简单解释 MapReduce 算法 一个有趣的例子 你想数出一摞牌中有多少张黑桃.直观方式是一张一张检查并且数出有多少张是黑桃? MapReduce方法则是: 给在座的所有玩家中分配这摞牌 让每个玩家 ...

最新文章

  1. 一起学spring--依赖注入---简单粗暴的例子展示
  2. Spring MVC中获取当前项目的路径
  3. ubuntu14.04LS中安装sogouPingyin
  4. 断言java_Java几种常用的断言风格你怎么选?
  5. python处理pcap文件_[转载]Python读取pcap文件
  6. 图片夹_【第8期】EHS大咖答疑解惑吊运事故的罪魁祸首之一:钢丝绳夹!不看不知道!...
  7. 阿里百川 WKWebView 无法拦截URL
  8. 微信扫码登陆或注册设计流程
  9. 什么是尾递归?javascript 尾递归优化
  10. [实战] Android 发短信 - SMS
  11. LabVIEW编程LabVIEW开发 西门子
  12. PID控制算法实践应用(一):PID算法的离散化
  13. 关于java中的finalize()方法
  14. 使用Lumberjack进行日志切割归档
  15. iphone文件app里无法连接服务器,苹果商店怎么打不开 无法连接到app store解决方法...
  16. python数据库开发 dga_图/Louvain/DGA乱谈
  17. 【读书笔记】《利用Python进行数据分析》第2版_第六章 数据载入、存储及文件格式
  18. python笑傲江湖_PHP 2019年继续笑傲江湖
  19. 移动互联网繁荣本质是什么
  20. 关于win7利用vs2010 MFC平台开发的软件在win10系统的电脑下无法运行的问题。

热门文章

  1. 提升自己的最好方式是什么呢?
  2. 泰克Tektronix示波器软件TDS520|TDS1001|TDS1002上位机软件NS-Scope
  3. 鸿蒙珠融入体内,逍遥至尊之诸天逍遥
  4. 免费MindManager2021最新版本地址win/mac思维导图工具 新增功能
  5. c语言航标知识点,书摘:迷惘时的航标——“人生哲学”
  6. 【PyG】文档总结以及项目经验(持续更新
  7. html制作星球,AE科幻星球制作教程
  8. java中为什么要用json_Java中json的使用和解析
  9. MIPS/RISC-V ALU设计
  10. img图片加载失败的处理