day08.MAPREDUCE详解大数据教程

day08.MAPREDUCE详解【大数据教程】

1. MAPREDUCE原理篇(1)

Mapreduce是一个分布式运算程序的编程框架,是用户开发“基于hadoop的数据分析应用”的核心框架;

Mapreduce核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布式运算程序,并发运行在一个hadoop集群上;

1.1为什么要MAPREDUCE

(1)海量数据在单机上处理因为硬件资源限制,无法胜任

(2)而一旦将单机版程序扩展到集群来分布式运行,将极大增加程序的复杂度和开发难度

(3)引入mapreduce框架后,开发人员可以将绝大部分工作集中在业务逻辑的开发上,而将分布式计算中的复杂性交由框架来处理

设想一个海量数据场景下的wordcount需求:

可见在程序由单机版扩成分布式时,会引入大量的复杂工作。为了提高开发效率,可以将分布式程序中的公共功能封装成框架,让开发人员可以将精力集中于业务逻辑。

而mapreduce就是这样一个分布式程序的通用框架,其应对以上问题的整体结构如下:

1.2 MAPREDUCE框架结构及核心运行机制

1.2.1结构

一个完整的mapreduce程序在分布式运行时有三类实例进程:

1.MRAppMaster:负责整个程序的过程调度及状态协调

2.mapTask:负责map阶段的整个数据处理流程

3.ReduceTask:负责reduce阶段的整个数据处理流程

1.2.2MR程序运行流程

1.2.2.1流程示意图

1.2.2.2流程解析

1.一个mr程序启动的时候,最先启动的是MRAppMaster,MRAppMaster启动后根据本次job的描述信息,计算出需要的maptask实例数量,然后向集群申请机器启动相应数量的maptask进程

2.maptask进程启动之后,根据给定的数据切片范围进行数据处理,主体流程为:

a) 利用客户指定的inputformat来获取RecordReader读取数据,形成输入KV对

b) 将输入KV对传递给客户定义的map()方法,做逻辑运算,并将map()方法输出的KV对收集到缓存

c) 将缓存中的KV对按照K分区排序后不断溢写到磁盘文件

3.MRAppMaster监控到所有maptask进程任务完成之后,会根据客户指定的参数启动相应数量的reducetask进程,并告知reducetask进程要处理的数据范围(数据分区)

4.Reducetask进程启动之后,根据MRAppMaster告知的待处理数据所在位置,从若干台maptask运行所在机器上获取到若干个maptask输出结果文件,并在本地进行重新归并排序,然后按照相同key的KV为一个组,调用客户定义的reduce()方法进行逻辑运算,并收集运算输出的结果KV,然后调用客户指定的outputformat将结果数据输出到外部存储

1.3MapTask并行度决定机制

maptask的并行度决定map阶段的任务处理并发度,进而影响到整个job的处理速度

那么,mapTask并行实例是否越多越好呢?其并行度又是如何决定呢?

1.3.1 mapTask并行度的决定机制

一个job的map阶段并行度由客户端在提交job时决定

而客户端对map阶段并行度的规划的基本逻辑为:

将待处理数据执行逻辑切片(即按照一个特定切片大小,将待处理数据划分成逻辑上的多个split),然后每一个split分配一个mapTask并行实例处理

这段逻辑及形成的切片规划描述文件,由FileInputFormat实现类的getSplits()方法完成,其过程如下图:

1.3.2FileInputFormat切片机制

1.切片定义在InputFormat类中的getSplit()方法2.FileInputFormat中默认的切片机制:

a) 简单地按照文件的内容长度进行切片

b) 切片大小,默认等于block大小

c) 切片时不考虑数据集整体,而是逐个针对每一个文件单独切片

比如待处理数据有两个文件:

经过FileInputFormat的切片机制运算后,形成的切片信息如下:

3.FileInputFormat中切片的大小的参数配置

通过分析源码,在FileInputFormat中,计算切片大小的逻辑:Math.max(minSize, Math.min(maxSize, blockSize));切片主要由这几个值来运算决定

因此,默认情况下,切片大小=blocksize

maxsize(切片最大值):

参数如果调得比blocksize小,则会让切片变小,而且就等于配置的这个参数的值

minsize(切片最小值):

参数调的比blockSize大,则可以让切片变得比blocksize还大

选择并发数的影响因素:

1.运算节点的硬件配置

2.运算任务的类型:CPU密集型还是IO密集型

3.运算任务的数据量

1.4 map并行度的经验之谈

如果硬件配置为2*12core + 64G,恰当的map并行度是大约每个节点20-100个map,最好每个map的执行时间至少一分钟。

如果job的每个map或者reduce task的运行时间都只有30-40秒钟,那么就减少该job的map或者reduce数,每一个task(map|reduce)的setup和加入到调度器中进行调度,这个中间的过程可能都要花费几秒钟,所以如果每个task都非常快就跑完了,就会在task的开始和结束的时候浪费太多的时间。

配置task的JVM重用可以改善该问题:(JVM重用技术不是指同一Job的两个或两个以上的task可以同时运行于同一JVM上,而是排队按顺序执行。)

(mapred.job.reuse.jvm.num.tasks,默认是1,表示一个JVM上最多可以顺序执行的task

数目(属于同一个Job)是1。也就是说一个task启一个JVM

如果input的文件非常的大,比如1TB,可以考虑将hdfs上的每个block size设大,比如设成256MB或者512MB

1.5ReduceTask并行度的决定

reducetask的并行度同样影响整个job的执行并发度和执行效率,但与maptask的并发数由切片数决定不同,Reducetask数量的决定是可以直接手动设置:

//默认值是1,手动设置为4

job.setNumReduceTasks(4);

如果数据分布不均匀,就有可能在reduce阶段产生数据倾斜

注意:reducetask数量并不是任意设置,还要考虑业务逻辑需求,有些情况下,需要计算全局汇总结果,就只能有1个reducetask

尽量不要运行太多的reduce task。对大多数job来说,最好rduce的个数最多和集群中的reduce持平,或者比集群的reduce slots小。这个对于小集群而言,尤其重要。

1.6MAPREDUCE程序运行演示

Hadoop的发布包中内置了一个hadoop-mapreduce-example-2.4.1.jar,这个jar包中有各种MR示例程序,可以通过以下步骤运行:

启动hdfs,yarn

然后在集群中的任意一台服务器上启动执行程序(比如运行wordcount):

hadoop jar hadoop-mapreduce-example-2.4.1.jar wordcount /wordcount/data /wordcount/out

2. MAPREDUCE实践篇(1)

2.1MAPREDUCE示例编写及编程规范

2.1.1编程规范

(1)用户编写的程序分成三个部分:Mapper,Reducer,Driver(提交运行mr程序的客户端)

(2)Mapper的输入数据是KV对的形式(KV的类型可自定义)

(3)Mapper的输出数据是KV对的形式(KV的类型可自定义)

(4)Mapper中的业务逻辑写在map()方法中

(5)map()方法(maptask进程)对每一个调用一次

(6)Reducer的输入数据类型对应Mapper的输出数据类型,也是KV

(7)Reducer的业务逻辑写在reduce()方法中

(8)Reducetask进程对每一组相同k的组调用一次reduce()方法

(9)用户自定义的Mapper和Reducer都要继承各自的父类

(10)整个程序需要一个Drvier来进行提交,提交的是一个描述了各种必要信息的job对象

1.7.2 wordcount示例编写

需求:在一堆给定的文本文件中统计输出每一个单词出现的总次数

(1)定义一个mapper类

(2)定义一个reducer类

(3)定义一个主类,用来描述job并提交job

2.2MAPREDUCE程序运行模式

2.2.1本地运行模式

(1)mapreduce程序是被提交给LocalJobRunner在本地以单进程的形式运行

(2)而处理的数据及输出结果可以在本地文件系统,也可以在hdfs上

(3)怎样实现本地运行?写一个程序,不要带集群的配置文件(本质是你的mr程序的conf中是否有mapreduce.framework.name=local以及yarn.resourcemanager.hostname参数)

(4)本地模式非常便于进行业务逻辑的debug,只要在eclipse中打断点即可

如果在windows下想运行本地模式来测试程序逻辑,需要在windows中配置环境变量:

%HADOOP_HOME%= d:/hadoop-2.6.1

%PATH% =%HADOOP_HOME%\bin

并且要将d:/hadoop-2.6.1的lib和bin目录替换成windows平台编译的版本

2.2.2集群运行模式

(1)将mapreduce程序提交给yarn集群resourcemanager,分发到很多的节点上并发执行

(2)处理的数据和输出结果应该位于hdfs文件系统

(3)提交集群的实现步骤:

A.将程序打成JAR包,然后在集群的任意一个节点上用hadoop命令启动$ hadoop jar wordcount.jar cn.itcast.bigdata.mrsimple.WordCountDriver inputpath outputpath

B.直接在linux的eclipse中运行main方法(项目中要带参数:mapreduce.framework.name=yarn以及yarn的两个基本配置)

C.如果要在windows的eclipse中提交job给集群,则要修改YarnRunner类

mapreduce程序在集群中运行时的大体流程:

附:在windows平台上访问hadoop时改变自身身份标识的方法之二:

3. MAPREDUCE中的Combiner

Combiner的使用要非常谨慎

因为combiner在mapreduce过程中可能调用也肯能不调用,可能调一次也可能调多次

所以:combiner使用的原则是:有或没有都不能影响业务逻辑

(1)combiner是MR程序中Mapper和Reducer之外的一种组件

(2)combiner组件的父类就是Reducer

(3)combiner和reducer的区别在于运行的位置:

Combiner是在每一个maptask所在的节点运行

Reducer是接收全局所有Mapper的输出结果;

(4) combiner的意义就是对每一个maptask的输出进行局部汇总,以减小网络传输量

具体实现步骤:

1.自定义一个combiner继承Reducer,重写reduce方法

2.在job中设置:job.setCombinerClass(CustomCombiner.class)

(5) combiner能够应用的前提是不能影响最终的业务逻辑

而且,combiner的输出kv应该跟reducer的输入kv类型要对应起来

3.MAPREDUCE原理篇(2)

3.1mapreduce的shuffle机制

3.1.1概述:

mapreduce中,map阶段处理的数据如何传递给reduce阶段,是mapreduce框架中最关键的一个流程,这个流程就叫shuffle;

shuffle: 洗牌、发牌——(核心机制:数据分区,排序,缓存);

具体来说:就是将maptask输出的处理结果数据,分发给reducetask,并在分发的过程中,对数据按key进行了分区和排序;

3.1.2主要流程:

Shuffle缓存流程:

shuffle是MR处理流程中的一个过程,它的每一个处理步骤是分散在各个map task和reduce task节点上完成的,整体来看,分为3个操作:

1.分区partition

2.Sort根据key排序

3.Combiner进行局部value的合并

3.1.3详细流程

1.maptask收集我们的map()方法输出的kv对,放到内存缓冲区中

2.从内存缓冲区不断溢出本地磁盘文件,可能会溢出多个文件

3.多个溢出文件会被合并成大的溢出文件

4.在溢出过程中,及合并的过程中,都要调用partitoner进行分组和针对key进行排序

5.reducetask根据自己的分区号,去各个maptask机器上取相应的结果分区数据

6.reducetask会取到同一个分区的来自不同maptask的结果文件,reducetask会将这些文件再进行合并(归并排序)

7.合并成大文件后,shuffle的过程也就结束了,后面进入reducetask的逻辑运算过程(从文件中取出一个一个的键值对group,调用用户自定义的reduce()方法)

Shuffle中的缓冲区大小会影响到mapreduce程序的执行效率,原则上说,缓冲区越大,磁盘io的次数越少,执行速度就越快

缓冲区的大小可以通过参数调整,参数:io.sort.mb默认100M

3.1.4详细流程示意图

3.2. MAPREDUCE中的序列化

3.2.1概述

Java的序列化是一个重量级序列化框架(Serializable),一个对象被序列化后,会附带很多额外的信息(各种校验信息,header,继承体系。。。。),不便于在网络中高效传输;

所以,hadoop自己开发了一套序列化机制(Writable),精简,高效

3.2.2Jdk序列化和MR序列化之间的比较

简单代码验证两种序列化机制的差别:

3.2.3自定义对象实现MR中的序列化接口

如果需要将自定义的bean放在key中传输,则还需要实现comparable接口,因为mapreduce框中的shuffle过程一定会对key进行排序,此时,自定义的bean实现的接口应该是:

public class FlowBean implements WritableComparable

需要自己实现的方法是:

3.3. MapReduce与YARN

3.3.1 YARN概述

Yarn是一个资源调度平台,负责为运算程序提供服务器运算资源,相当于一个分布式的操作系统平台,而mapreduce等运算程序则相当于运行于操作系统之上的应用程序

3.3.2 YARN的重要概念

1.yarn并不清楚用户提交的程序的运行机制

2.yarn只提供运算资源的调度(用户程序向yarn申请资源,yarn就负责分配资源)

3.yarn中的主管角色叫ResourceManager

4.yarn中具体提供运算资源的角色叫NodeManager

5.这样一来,yarn其实就与运行的用户程序完全解耦,就意味着yarn上可以运行各种类型的分布式运算程序(mapreduce只是其中的一种),比如mapreduce、storm程序,spark程序,tez ……

6.所以,spark、storm等运算框架都可以整合在yarn上运行,只要他们各自的框架中有符合yarn规范的资源请求机制即可

7.Yarn就成为一个通用的资源调度平台,从此,企业中以前存在的各种运算集群都可以整合在一个物理集群上,提高资源利用率,方便数据共享

3.3.3Yarn中运行运算程序的示例

mapreduce程序的调度过程,如下图

4. MAPREDUCE实践篇(2)

4.1. Mapreduce中的排序初步

4.1.1需求

对日志数据中的上下行流量信息汇总,并输出按照总流量倒序排序的结果

数据如下:

4.1.2分析

基本思路:实现自定义的bean来封装流量信息,并将bean作为map输出的key来传输

MR程序在处理数据的过程中会对数据排序(map输出的kv对传输到reduce之前,会排序),排序的依据是map输出的key

所以,我们如果要实现自己需要的排序规则,则可以考虑将排序因素放到key中,让key实现接口:WritableComparable

然后重写key的compareTo方法

4.1.3实现

1.自定义的bean

2.mapper 和 reducer

4.2. Mapreduce中的分区Partitioner

4.2.1需求

根据归属地输出流量统计数据结果到不同文件,以便于在查询统计结果时可以定位到省级范围进行

4.2.2分析

Mapreduce中会将map输出的kv对,按照相同key分组,然后分发给不同的reducetask

默认的分发规则为:根据key的hashcode%reducetask数来分发

所以:如果要按照我们自己的需求进行分组,则需要改写数据分发(分组)组件Partitioner

自定义一个CustomPartitioner继承抽象类:Partitioner

然后在job对象中,设置自定义partitioner:job.setPartitionerClass(CustomPartitioner.class)

4.2.3实现

4.3. mapreduce数据压缩

4.3.1概述

这是mapreduce的一种优化策略:通过压缩编码对mapper或者reducer的输出进行压缩,以减少磁盘IO,提高MR程序运行速度(但相应增加了cpu运算负担)

1.Mapreduce支持将map输出的结果或者reduce输出的结果进行压缩,以减少网络IO或最终输出数据的体积

2.压缩特性运用得当能提高性能,但运用不当也可能降低性能

3.基本原则:

运算密集型的job,少用压缩

IO密集型的job,多用压缩

4.3.2 MR支持的压缩编码

4.3.3 Reducer输出压缩

在配置参数或在代码中都可以设置reduce的输出压缩

1.在配置参数中设置

mapreduce.output.fileoutputformat.compress=false

mapreduce.output.fileoutputformat.compress.codec=org.apache.hadoop.io.compress.DefaultCodec

mapreduce.output.fileoutputformat.compress.type=RECORD

2.在代码中设置

4.3.4 Mapper输出压缩

在配置参数或在代码中都可以设置reduce的输出压缩

1.在配置参数中设置

mapreduce.map.output.compress=false

mapreduce.map.output.compress.codec=org.apache.hadoop.io.compress.DefaultCodec

2.在代码中设置:

4.3.5压缩文件的读取

Hadoop自带的InputFormat类内置支持压缩文件的读取,比如TextInputformat类,在其initialize方法中:

4.4.更多MapReduce编程案例

4.4.1 reduce端join算法实现

1.需求:

订单数据表t_order:

商品信息表t_product

假如数据量巨大,两表的数据是以文件的形式存储在HDFS中,需要用mapreduce程序来实现一下SQL查询运算:

2.实现机制:

通过将关联的条件作为map输出的key,将两表满足join条件的数据并携带数据所来源的文件信息,发往同一个reduce task,在reduce中进行数据的串联

缺点:这种方式中,join的操作是在reduce阶段完成,reduce端的处理压力太大,map节点的运算负载则很低,资源利用率不高,且在reduce阶段极易产生数据倾斜

解决方案:map端join实现方式

4.4.2 map端join算法实现

1.原理阐述

适用于关联表中有小表的情形;

可以将小表分发到所有的map节点,这样,map节点就可以在本地对自己所读到的大表数据进行join并输出最终结果,可以大大提高join操作的并发度,加快处理速度

2.实现示例

--先在mapper类中预先定义好小表,进行join

--引入实际场景中的解决方案:一次加载数据库或者用distributedcache

4.4.3 web日志预处理

1.需求:

对web访问日志中的各字段识别切分

去除日志中不合法的记录

根据KPI统计需求,生成各类访问请求过滤数据

2.实现代码:

a)定义一个bean,用来记录日志数据中的各数据字段

b)定义一个parser用来解析过滤web访问日志原始记录

c) mapreduce程序

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180515G01YNH00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券