一、概念
MapReduce是一个计算模型,计算过程分两个阶段:Map、Reduce。每个阶段都是用键值对<key, value>作为输入、输出。Map表示映射,Reduce表示化简。
二、一个MapReduce的例子(著名的WordCount)
该编程模型提供给用户的接口是Map和Reduce两个函数。下面是一个Map、Reduce的例子。
map(String key, String value) { // key: file name // value: file contents for each word w in value: CalcIntermediateResult(w, "1"); } reduce(String key, Iterator values) { // key: a word // values: a list of counts int result = 0; for each v in values: result += ParseInt(v); outputFinalResult(AsString(result)); }
Map阶段接收一个<key, value>作为输入,产生一个<key, value>的中间结果,然后将具有相同key的<key, value>集合起来,形成<key, Iterator<value> >,发送给Reduce;
Reduce阶段接收Map阶段的<key, Iterator<value> >作为输入,合并具有相同key的value值,形成一个较小的<key, value>值作为输出。
三、MapReduce的工作流程
(1)用户文件输入。用户程序首先将文件上传到HDFS中,默认情况下以64M为单位进行分片,文为M块,每个块会保存多个副本。
(2)master分配任务。Master节点为主节点,负责分配任务,尽量将任务分配到空闲节点上。
(3)Map阶段。被分配了任务的map worker节点读取数据块,从中解析出<key, value>内容,发送给用户自定义的map函数,由map生成中间结果。
(4)写入本地临时文件。map函数将产生的中间结果分区后写入到本地磁盘上,之后这些文件的存储位置将会发送给master节点。
(5)Reduce worker读取文件。reduce worker节点在收到master发来的任务、数据块信息后,去map worker节点读取数据。在读取到所有数据后,将相同key的节点聚合到一起。
(6)Reduce阶段。reduce worker将按key排序后的<key, value>传递给用户自定义的reduce函数,产生最终结果。
(7)结束。当所有的map、reduce程序运行完后,master告诉用户程序处理完毕。
四、异常处理
(1)worker节点故障
worker节点每个一段时间(30s/1min)会通知master节点,告诉master自己还活着,这叫做心跳检测。master如果长时间没有收到某个worker的消息,就断定该worker节点发生故障,这时该worker的map、reduce任务就会被重置,然后重新指定给其他节点。如果是故障的是map worker节点,master节点还需告诉其他所有的reduce worker节点,该map worker节点发生变化。
当map worker节点故障时,由于其运行的结果存储在本地,已经不能获取,因此该map任务就需要重新执行。而Reduce worker节点的输出保存在全局文件系统上,因此不需要重新执行。
(2)master节点故障
采用快照的方式,master节点周期性地将保存的文件列表、文件块列表、map/reduce任务列表等写入磁盘(或者发给备用master节点),即检查点(checkpoint),如果master节点故障了,就从最近的检查点开始工作(或启动备用master节点)。