MapReduce应该做更少的事情
MapReduce 做的事情太多了。相比 unix 思想,它更多的是提供了一种策略(Policy),而非一种机制(Machanism)。
对于并行计算,如果我仅仅需要一种机制,暂且把这种机制叫做S,那么S只需要提供:
- 任意切分原始输入 ——split
- 无依赖的计算 ——map
- 按依赖切分中间结果 ——partition
- 有依赖的计算 ——reduce
- 容错 ——MR 矩阵(包括数据)
MapReduce当然提供了这个机制,只是,以它自己特定的方式(Policy)提供——就是排序。
Map 阶段是无依赖的计算,Reduce是有依赖的计算。Map的输入集合可以是任意顺序,任意切分,Combine可以看作只是为了提升效率而提前解决局部(local)依赖。
Reduce用来解决依赖,这个依赖,是按照Key的依赖,相同的Key和它的Value集合,是一个依赖集。
MapReduce 使用先排序,然后把整个Key-ValueList发送给应用接口,解决了这个问题。这样做,应用代码可以极大简化。但是,同时,这也严重地限制了性能。因为它做的事情,不是S的最小集。
一个S的最小集的实现:
- Map 处理每条输入记录——无依赖的计算
- Map 将处理后的记录按某种 Hash 规则进行切分,发送到各个 Reduce
- Map 发送记录的同时,将它备份到硬盘(或内存)
- Reduce 按自己的方式进行有依赖的计算(可以排序,也可以使用Hash<Key, *> 来解依赖)
如果 WordCount 使用这种方式,可以大幅提高速度,并减少内存用量。