Hadoop理论之MapReduce

1.MapReduce的主要功能:
      1)数据划分和计算任务调度:系统自动将一个作业(Job)待处理的 大数据划分为很多个数据块,每个数据块对应于一个计算任务(Task),并自动 调度计算节点来处理相应的数据块。作业和任务调度功能主要负责分配和调度计算节点(Map节点或Reduce节点),同时负责监控这些节点的执行状态,并 负责Map节点执行的同步控制。
      2)数据/代码互定位:为了减少数据通信,一个基本原则是本地化数据处理,即一个计算节点尽可能处理其本地磁盘上所分布存储的数据,这实现了代码向 数据的迁移;当无法进行这种本地化数据处理时,再寻找其他可用节点并将数据从网络上传送给该节点(数据向代码迁移),但将尽可能从数据所在的本地机架上寻 找可用节点以减少通信延迟。
      3)系统优化:为了减少数据通信开销,中间结果数据进入Reduce节点前会进行一定的合并处理;一个Reduce节点所处理的数据可能会来自多个 Map节点,为了避免Reduce计算阶段发生数据相关性,Map节点输出的中间结果需使用一定的策略进行适当的划分处理,保证相关性数据发送到同一个 Reduce节点;此外,系统还进行一些计算性能优化处理,如对最慢的计算任务采用多备份执行、选最快完成者作为结果。
      4)出错检测和恢复:以低端商用服务器构成的大规模MapReduce计算集群中,节点硬件(主机、磁盘、内存等)出错和软件出错是常态,因此 MapReduce需要能检测并隔离出错节点,并调度分配新的节点接管出错节点的计算任务。同时,系统还将维护数据存储的可靠性,用多备份冗余存储机制提 高数据存储的可靠性,并能及时检测和恢复出错的数据。
2.MapReduce的主要技术特征
      MapReduce设计上具有以下主要的技术特征:
1)向“外”横向扩展,而非向“上”纵向扩展
      即MapReduce集群的构建完全选用价格便宜、易于扩展的低端商用服务器,而非价格昂贵、不易扩展的高端服务器。对于大规模数据处理,由于有大 量数据存储需要,显而易见,基于低端服务器的集群远比基于高端服务器的集群优越,这就是为什么MapReduce并行计算集群会基于低端服务器实现的原 因。
2)失效被认为是常态
      MapReduce集群中使用大量的低端服务器,因此,节点硬件失效和软件出错是常态,因而一个良好设计、具有高容错性的并行计算系统不能因为节点 失效而影响计算服务的质量,任何节点失效都不应当导致结果的不一致或不确定性;任何一个节点失效时,其他节点要能够无缝接管失效节点的计算任务;当失效节 点恢复后应能自动无缝加入集群,而不需要管理员人工进行系统配置。MapReduce并行计算软件框架使用了多种有效的错误检测和恢复机制,如节点自动重 启技术,使集群和计算框架具有对付节点失效的健壮性,能有效处理失效节点的检测和恢复。
3)把处理向数据迁移
      传统高性能计算系统通常有很多处理器节点与一些外存储器节点相连,如用存储区域网络(Storage Area,SAN Network)连接的磁盘阵列,因此,大规模数据处理时外存文件数据I/O访问会成为一个制约系统性能的瓶颈。为了减少大规模数据并行计算系统中的数据 通信开销,代之以把数据传送到处理节点(数据向处理器或代码迁移),应当考虑将处理向数据靠拢和迁移。MapReduce采用了数据/代码互定位的技术方 法,计算节点将首先尽量负责计算其本地存储的数据,以发挥数据本地化特点,仅当节点无法处理本地数据时,再采用就近原则寻找其他可用计算节点,并把数据传 送到该可用计算节点。
4)顺序处理数据、避免随机访问数据
      大规模数据处理的特点决定了大量的数据记录难以全部存放在内存,而通常只能放在外存中进行处理。由于磁盘的顺序访问要远比随机访问快得多,因此 MapReduce主要设计为面向顺序式大规模数据的磁盘访问处理。为了实现面向大数据集批处理的高吞吐量的并行处理,MapReduce可以利用集群中 的大量数据存储节点同时访问数据,以此利用分布集群中大量节点上的磁盘集合提供高带宽的数据访问和传输。
5)为应用开发者隐藏系统层细节
      软件工程实践指南中,专业程序员认为之所以写程序困难,是因为程序员需要记住太多的编程细节(从变量名到复杂算法的边界情况处理),这对大脑记忆是 一个巨大的认知负担,需要高度集中注意力;而并行程序编写有更多困难,如需要考虑多线程中诸如同步等复杂繁琐的细节。由于并发执行中的不可预测性,程序的 调试查错也十分困难;而且,大规模数据处理时程序员需要考虑诸如数据分布存储管理、数据分发、数据通信和同步、计算结果收集等诸多细节问题。 MapReduce提供了一种抽象机制将程序员与系统层细节隔离开来,程序员仅需描述需要计算什么(What to compute),而具体怎么去计算(How to compute)就交由系统的执行框架处理,这样程序员可从系统层细节中解放出来,而致力于其应用本身计算问题的算法设计。
6)平滑无缝的可扩展性
      这里指出的可扩展性主要包括两层意义上的扩展性:数据扩展和系统规模扩展性。理想的软件算法应当能随着数据规模的扩大而表现出持续的有效性,性能上 的下降程度应与数据规模扩大的倍数相当;在集群规模上,要求算法的计算性能应能随着节点数的增加保持接近线性程度的增长。绝大多数现有的单机算法都达不到 以上理想的要求;把中间结果数据维护在内存中的单机算法在大规模数据处理时很快失效;从单机到基于大规模集群的并行计算从根本上需要完全不同的算法设计。 奇妙的是,MapReduce在很多情形下能实现以上理想的扩展性特征。多项研究发现,对于很多计算问题,基于MapReduce的计算性能可随节点数目 增长保持近似于线性的增长。
3.MR简介
map是分思想,reduce是合思想。

MR计算框架与其他框架的对比:
MR 分布式计算框架 离线计算框架
Storm 流式计算框架 实时计算框架
Spark 内存计算框架 快速得到结果的计算
MR移动计算但不移动数据
MR的几个阶段:
1.split 将block中的数据分块传入至map任务中执行(分块的大小有一个默认的计算公式)
2.map 简单来说是以行数据的偏移量作为key,行内容作为value进行你想要进行的操作,而后以键值对的形式输出。
3.shuffler(合并和排序) map和reduce之间的步骤,这个阶段属于不断被优化和改进的代码库的一部分。从许多方面来看,shuffle是MapReduce的“心脏”,是奇迹发生的地方。
partition:可以把Map的输出按照某种Key值重新切分和组成N份,把key值符合某种范围的输出送到特定的reduce去处理。(hashcode取模的方式)(可自定义)在此处可以一定程度上解决reduce节点的数据倾斜,负载均衡问题。
sort:对partiton后的值进行排序,如果reduce阶段也需要排序则可按归并排序理解。(可自定义)
spill:当map输出结果的大小超过一定限制,为了充分利用内容。它会将数据溢写进磁盘(并不是HDFS,该中间结果在传入reduce之后就丢弃了,将它存储至HDFS,有点小题大做)。
merge:map有时候可能是多线程执行,需要将map结果按分区进行合并。
4.分组和combiner:
在将map中间结果给到reduce的过程中,我们还可以进行一些工作。因为map到reduce节点之间的网络带宽非常珍贵,我们必须使得中间结果越少越好。如分组和combiner操作。下面详细介绍:
1.分组
在Hadoop中的默认分组规则中,也是基于Key进行的,会将相同key的value放到一个集合中去。这里有一个简单的例子帮助理解,因为我们自定义了一个新的key,它是以两列数据作为key的:1 1;2 1;2 2;3 1;3 2;3 3,因此这6行数据中每个key都不相同,也就是说会产生6组,它们是:1 1,2 1,2 2,3 1,3 2,3 3。而实际上只可以分为3组(只要第一个值相同则为一组),分别是1,2,3。从这个例子上来看,我们可以自己定义分组函数。
这里需要弄懂partition和分组的区别,分区的目的是让map的输出结果按照一定规则分发至不同的reduce执行,分组则是将相同key(默认,我们可自定义)的健值对组合在一起(统一key,value编程一个集合)。
2.combiner
Combiner的作用是把一个map产生的多个 <KEY,VALUE>合并成一个新的 <KEY,VALUE>,然后再将新 <KEY,VALUE>的作为reduce的输入;
在map函数与reduce函数之间多了一个combine函数,目的是为了减少map输出的中间结果,这样减少了reduce复制map输出的数据, 减少网络传输负载
并不是所有情况下都能使用Combiner,Combiner适用于对记录汇总的场景(如 求和),但是, 求平均数的场景就不能使用Combiner了。如果可以使用Combiner,一般情况下,和我们的reduce函数是一致的。
5.自定义编程简单介绍(可根据业务需求进行部分或整体自定义)
split大小自定义 则是将datanode上的block分块传入map函数进行处理。我们可以通过自定义split的块大小。
自定义key对象:如果该对象需要被mapreduce使用必须实现WritableComparable接口.
需要重写里面的方法
方法一 readFields (RPC 从二进制的流里面去读取数据成我们的对象)反序列化的过程
方法二 write(序列化) 针对该对象的读写操作
方法三 compareTo 对象的比较
map函数自定义 写自定义的map程序都需要继承Mapper类,特殊的数据格式.(LongWritable,Text ,Intwritable ),通常输入为为文本数据,mr框架将按行读取数据,同时以行偏移量作为key,以内容作为值。中间处理过程可通过自己编程定义,但输出结果必须为<key,value>对.context.write,map的输出 每次调用map方法会传入split中一行数据 StringTokenizer(String的分词器对象,默认就是用空格切分 .
自定义排序类;
该排序类如果需要直接被mapreduce使用的话,需要继承WritableComparator
需要一个构造方法传入值。super(排序对象.class,true);
重写compare方法(这个是实现自定义排序的关键类)
自定义分区
继承Partitioner类 重写getPartition分区。
自定义分组
shuffle key相同的合并 可能并不符合要求,
跟前面的自定义排序类一样。重写compare方法 比较需要分区的内容,返回相同的值则会在同一个组内。
6.其他
最终程序的执行,新建一个jop,需要传入一个conf文件,告诉jop传入至 jobtracker。接下来需要设置job的各个值,包过map,reduce,shuffle阶段自定义的函数等。还需定义输入文件的路径输出文件的路径,以及输入文件的类型和输出文件的类型等。在程序编写完毕之后有两种运行方式:1.通过eclipse跟hadioop的插件,在eclipse中直接运行。2.可以通过eclipse打成jar包(在命令行打jar包比较麻烦,详情可查看 https://blog.csdn.net/qq_36663613/article/details/80005534),直接在命令行向hadoop提交作业。mapreduce看起来比较简单,人们对它处理复杂业务的能力表示担忧。但是,它的表现非常出人意料,因为它可以多个mapreduce任务可以嵌套。

猜你喜欢

转载自blog.csdn.net/qq_36663613/article/details/80218413