MapReduce编程模型的要点

背景
MapReduce现在基本已经成为分布式并行编程框架的Bible,很多分布式计算引擎的实现[Hadoop][CIEL][Twister][Transformer][MR-mpi][Phoenix][Dryad]都将MapReduce作为一个核心的编程模型。

MapReduce编程模型是什么?
很多人都认为MapReduce只有这样两个过程构成:
Map过程:Map(k1,v1) → list(k2,v2)
Reduce过程:
Reduce(k2, list (v2)) → 
list(v3)
会找到一些图来辅助对于MapReduce的理解:

MapReduce编程模型的要点

哪些是MapReduce过程的关键点?
1)Map阶段的数据本地性的考虑。
2)Map中间结果的归并,由多个Spill文件归并成一个大文件。
3)Reduce拷贝数据的过程
对于一个具体的问题,更多的时候,确定Map、Reduce过程的操作并不困难,关键的问题是MapReduce对于数据的组织和传输问题。
1)map是数据本地性、并行化的关键步骤。对于一个大文件,它起始位置放在哪里,如何对于map阶段划分成小文件,如何协调小文件的节点内部分发和task调度的配合。下面简单介绍几个开源版本的做法:
[Hadoop]的成功在于HDFS与MapReduce编程模型的配合与协作。HDFS按照block来存储大文件,每个DataNode存储一定数量的block,这些block的元数据信息可以通过HDFS的API获得。Hadoop根据block的个数初始化map的个数(默认方式),taskScheduler根据block的位置,调度一个map task,这里启用了Data Locality,会首先将MapTask调度到block所在的TaskTracker节点。当然,在Hadoop集群高负载的情况下,Data Locality的命中率不高,Berkeley在[Eurosys2010 Delay Scheduling]提出在不满足Data Locality的情况下,让该task等待一会,然后再被调度,这是调度问题,和上面讨论的问题还不属于一个层次。
[NSDI11 CIEL]它的开源版本叫做SkyWriting,使用的python开发的。该编程语言的好处,开发速度快,对于用户而言写程序入门特别低。CIEL是一个基于预测的动态DAG分布式计算框架,根据作业执行的需求,不断分裂出新的task,它对于输入数据管理之快基本没有做什么工作,只是使用一个全局的名字空间,保证对于不同节点上文件文件访问的统一接口。例子:
input_data = [ref("ciel://host137/chunk0"),
ref("ciel://host223/chunk1"),
...];
curr = ...; // Initial guess at the result.
这种做法的问题在于,用户需要组织输入大数据的切分和迁移。在我理解,一个完整的编程模型,必须包括对于要处理数据的组织,不然这块工作交由上层用户来维护,体验不好。
[Phoenix++]是由Stanford大学出品的一个款MapReduce产品,它实现的是shared Memory MapReduce,目标在于多核多处理器的大型服务器,用一台机器通过多线程实现了MapReduce。整个代码使用C+内嵌的汇编实现,很佩服Stanford的技术,里面用到了很多编程优化的技术,非常给力。看了它们的代码,我个人觉得比《编程之美》《编程珠玑》有意思的多了。Stanford CS人能力还是很强的,所以US有两个大学的开源版本的质量很强,一个是我最为崇拜的Berkeley,另外一个就是Stanford.我找了一些benchmark测了一下,phoenix++效率惊人,如果你有一个性能很棒的服务器,不如好好研究一些这个MapReduce吧。它没有理论上的JobTracker和TaskTracker,(可能编译的时候会出现arch上冲突造成error,没关系,给我发邮件,我告诉你怎么做,哎,我给Phoenix-2.0.0做了这么长的广告。)
言归正传:它是怎么组织数据给每个map呢?
通过mmap将本地文件全部导入内存中,然后启用多个pthread线程,默认是8个,将文件映射的内存区域,计算mapTask的个数,并且按照mapTask的个数切分mmap映射的内存,分别交给pthread来处理。在内存充足的情况下,把数据全部放在内存里处理,并且没有map到reduce阶段的网络IO和磁盘IO的开销,性能还是很不错的。Phoenix的设计从开始就面向的性能卓越的服务器,这与Hadoop架构在普通服务器或者Commodity machine的思想是不同的。

为了写一篇有营养的文章,我准备接下来在Hadoop MapReduce编程模型上多说几句。

Hadoop如何实现大文件与多个mapTask的映射
首先,我来给大家提几个问题?
1)MapReduce处理一般都是大文件,那么大文件要切分成各个小文件才能处理吗?
2)MapReduce的过程在什么阶段处理了大文件,对它生成了索引文件了吗?
3)MapTask的个数与文件的什么参数相关,程序可以设置吗?

这些问题在初期写Hadoop程序的时候,困扰了我很久,后来随着代码的深入理解,问题才一个又一个地揭开。
JobSubmiiter在将作业提交给JobTracker之前,回答了上面所说的三个问题。

两类Split文件:

在Hadoop中有两类split文件,一类是the split meta information, 另外一类是the raw split information, the split meta information被JobTracker使用来构建tasks的数据本地性的组织结构,另外一个类是 the raw split information 指定每一个MapTask需要读取数据的位置。这两个类分别为org.apache.hadoop.mapreduce.split.JobSplit.TaskSplitMetaInfo,org.apache.hadoop.mapreduce.split.SplitMetaInfo

JobSubmiiter处理生成split文件的函数:(有注释)
 private <T extends InputSplit>
  int writeNewSplits(JobContext job, Path jobSubmitDir) throws IOException,
      InterruptedException, ClassNotFoundException {
    Configuration conf = job.getConfiguration();
//通过反射获取Job设置的输入格式信息,InputFormat的接口一般有两个getSplits,getRecordReader,其中Splits是分割大文件,RecordReader是为每一个map()函数处理所使用。
    InputFormat<?, ?> input =
      ReflectionUtils.newInstance(job.getInputFormatClass(), conf);

//使用job指定的输入数据格式类来获取splits,假定用户使用了FileInputFormat,该类默认使用文件block的大小来划分InputSplit,因此,在不更改源码的过程中修改它,可以使用通过配置hdfs-site.xml中的property,
,另外,我们可以直接继承FileInputFormat,只需重载getSplits的方法,按照我们希望的大小对此划分

    List<InputSplit> splits = input.getSplits(job); //在FileInputFormat使用的是FileSplit,如果要是重载getSplits方法还得你还得看看FileSplit怎么用的. 
    T[] array = (T[]) splits.toArray(new InputSplit[splits.size()]);

    // sort the splits into order based on size, so that the biggest
    // go first
    Arrays.sort(array, new SplitComparator());
    JobSplitWriter.createSplitFiles(jobSubmitDir, conf, 
        jobSubmitDir.getFileSystem(conf), array);//调用JobSplitWriter生成TaskSplitMetaInfo和SplitMetaInfo
    return array.length; //返回的值其实就是number of map Task.
  }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值