MapReduce编程范型是本书所要讲述内容的核心基础重点。截至目前,MapReduce框架已被广泛的用于大数据的处理过程(four methods)。Hadoop系统对MapReduce框架的实现具有如下几个重要特征:
使用商用级别的硬件。需要注意的是这个商用硬件的要求不是指笔记本或者台式机。尽管计算集群是商用级别,但是我们可以使用常用的硬件设备来搭建。
无需事先定义数据划分准则来把数据分配到各个计算节点。
用户仅需要定义两个独立的处理过程:Map和Reduce。
本书会重点深入地讲解MapReduce框架。总体上说,MapReduce框架需要用户定义一个Map处理和Reduce处理。当Hadoop系统实现MapReduce时,数据常常按照64~128MB数据块大小进行分发,每个数据块会被复制两次(Hadoop系统数据备份默认参数为3)。在计算每个州的2000年的总销售额,并按照州排序的例子中,所有的销售数据都会分割为大量的数据块(大小64~128MB),加载到Hadoop分布式文件系统(Hadoop Distributed File System,HDFS)。
MapReduce程序启动的时候,Hadoop系统会把程序运行依赖库(包括用户自定义Map处理和Reduce处理)拷贝到各个计算节点。
各个计算节点按照调度执行Map任务,该Map任务会读取包含销售数据的数据块。每个Mapper(各自节点上的)会逐条读取数据块中的数据记录(Record),并过滤掉无用数据,仅保留2000年的数据。对应所输入的数据记录,Mapper会输出一条包含键/值对(key/value pair)的数据记录。如果读入的销售数据是2000年的,那么其键(key)就是州,其值(value)就是从读入数据记录中获取的销售数字。
最后,Reducer会从每个Mapper的输出中获取那些键/值对,运行Reducer的数量是可以配置的。各个键会被发送到特定Reducer进行处理,确保相同的键仅被相同的Reducer处理。各个Reducer把接受的键/值对中的销售数字相加。Reducer接受的数据格式是键(州)和这个键对应的销售数字列表(销售记录是2000年的)。输出结果写回HDFS中。客户端从HDFS上读取结果数据后,对结果按州排序。最后这个步骤也可以交给Reducer完成,因为Reducer在接受它要处理的键时,这些键是已经排序完成的。本例中,为了达到按州排序的目的,我们需要把Reducer的运行数量严格限制为1。可是由于Mapper和Reducer之间传输数据会引起网络I/O,这样可能会导致网络拥塞。本书的后面部分会详细地讨论这个问题。
下面列出了MapReduce编程模型的几个要点特征,这些特征同样符合前文中给出的大数据系统定义:
数据以较大的数据块的形式存放在HDFS上。HDFS是一个分布式文件系统,数据块分散存储到各个节点,数据块是有冗余的。
程序运行依赖库,包括Map和Reduce代码被复制发送到所有的任务节点。
每个计算节点仅读取节点本地数据。集群中所有节点运行Mapper,从节点本地读取数据到Mapper中(大多数情况下,哪个节点的Mapper读取哪个节点磁盘的数据块,这是由调度程序管理决定的。调度程序可能会分配某个节点的Mapper任务来处理远程节点的数据块,以保持集群中的所有节点负载均衡)。
数据被每个节点的任务以数据块的方式一次性顺序读取(数据块大小一般为64~128MB)。
MapReduce编程范型的一个重要不足是它不适合迭代算法。大量的数据科学计算算法很自然就要使用迭代,并最终收敛于一个解。当我们使用这样的算法的时候,MapReduce编程范型需要我们把每个迭代过程放到相互独立的MapReduce任务中去。每次迭代产生的数据输出作为下次迭代计算的数据输入。但是,由于MapReduce任务每次都要从持久性存储中重新读取数据,所以每次迭代产生的结果需要存到持久性存储中供下次迭代计算使用。这个过程导致了不必要的I/O操作,并对系统吞吐量造成重大影响。这样的问题在下面即将讲到的关于BSP类型系统的讲解中,也有论述。