文章目录
MapReduce定义
- MapReduce时一个分布式运算程序的编程框架,是用户开发基于Hadoop的数据分析应用的核心框架
- MapRdcue核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布式运算程序,并发运行在一个Hadoop集群上。
MapReduce的优点
- MapReduce易于编程:
- MapReduce简单的实现一些接口,就可以完成一个分布式程序,这个分布式程序可以分布到大量廉价的节点上运行
- 良好的扩展性:
- 当集群的计算资源不能得到满足的时候,可以通过简单的增加机器来扩展它的计算能力。
- 高容错性:
- MapReduce设计的目的就是为了使程序能够部署在廉价的PC机器上,这要求MapReduce具有很高的容错性。比如其中一台机器挂了,MapReduce可以把这台机器上的计算任务转移到另一个节点上运行,不至于这个任务运行失败,而且这个过程不需要人工参与,而是完全由Hadoop内部完成的。
- 适合PB级以上海量数据的离线处理
- MapReduce可以实现上千台服务器集群并发工作,提供数据处理能力。
MapReduce的缺点
- 不适合实时计算:
- MapReduce无法像mysql一样,在毫秒或秒级内返回结果。
- 不擅长流式计算
- 流式计算的输入数据是动态的,而MapReduce的输入数据是静态的,不能动态变化,这是因为MapReduce自身的设计特点决定了数据源必须是静态的。
- 不擅长有向图计算:
- 即多个应用程序存在依赖关系,后一个应用程序的输入为前一个的输出,MapReduce可以这么做,但是每个MapReduce作为的输出结果都会写入到磁盘,会造成大量磁盘同时在做I/O操作,导致性能非常低下。
MapReduce核心思想
- MapReduce的思想核心是分而治之,充分利用了并行处理的优势。
- MapReduce任务过程是分为两个处理阶段:
- Map阶段:Map阶段的主要作用是“分”,即把复杂的任务分解为若干个“简单的任务”来并行处理。Map阶段的这些任务可以并行计算,彼此间没有依赖关系。
- Reduce阶段:Reduce阶段的主要作用是“合”,即对map阶段的结果进行全局汇总。
- MapReduce编程模型只能包含一个Map阶段和一个Reduce阶段,如果用户的业务逻辑非常复杂,那就只能多个MapReduce程序,串行运行。
MapReduce程序组成
- 一个MapReduce程序由三个部分组成:Mapper阶段,Reducer阶段,运行作业的代码(Driver)阶段
- Mapper阶段:
- Mapper继承了org.apache.hadoop.mapreduce.Mapper类重写了其中的map方法。
- 重写的Map方法作用:map方法其中的逻辑就是用户希望mr程序map阶段如何处理的逻辑;
- Maper的输入数据是KV对的形式(kv类型可以自定义)
- Maper的输出数据是KV对的形式(kv类型可以自定义)
- map()方法(MapTask进程)对每个<K,V>调用一次。
- Reducer阶段
- Reducer承了org.apache.hadoop.mapreduce.Reducer类重写了其中的reduce方法。
- 重写的Reduce方法作用:reduce方法其中的逻辑是用户希望mr程序reduce阶段如何处理的逻辑;
- Reducer阶段的输入数据类型对应Mapper的输出数据类型,KV形式
- ReduceTask进程对一组相同key的<k,v>组调用一次reduce()方法
- 运行作业的代码(Driver)阶段
- Driver阶段相当于Yarn集群的客户端,用于提交我们整个程序到Yarn集群,提交的是封装了MapReducer程序相关运行参数的job对象。
MapReduce进程组成
- 一个完整的MapReduce程序在分布式运行时有三类实例进程:MapReduceAppMaster,MapTask以及ReduceTask
- MapReduceAppMaster:负责整个程序的过程调度以及状态协调
- MapTask:负责Map阶段的整个数据处理流程。
- ReduceTask:负责Reduce阶段的整个数据处理流程。
Hadoop序列化
- 序列化:就是把内存中的对象,转换成字节序列(或其他数据传输协议)以便于存储到磁盘(持久化)和网络传输。序列化需要把对象序列化成二进制的结构。
- 反序列化:就是将收到字节序列(或其他数据传输协议)或是磁盘的持久化数据,转换为内存中的对象。
Hadoop为什么要进行序列化
- 一般来说,动态的数据只保留在内存中,关机断电就没有了,而且内存中数据只能由本地的进程使用,不能通过网络发送到另一台计算机上,然后序列化可以将本地的数据对象发送到另一台计算机上。
Hadoop为什么不使用java自带serializable?
- java的序列化是一个重量级框架serializable,一个对象被序列化后,会携带很多额外信息比如校验信息,Header,继承体系等。不便于在网络中高效传输。所以Hadoop不使用java自带serializable
- Hadoop有一套自己的序列化格式。在Hadoop中,集群中多个节点的进程间的通信是通过RPC(远程过程调用:Remote Procedure Call)实现;
- RPC将消息序列化成二进制流发送到远程节点,远程节点再将接收到的二进制数据反序列化为原始的消息。因此RPC追求特点:紧凑:数据更紧凑,能充分利用网络带宽资源,快速:序列化和反序列化的性能开销更低
- Hadoop使用的是自己的序列化格式Writable,它比java的序列化serialization更紧凑速度更快。
Hadoop序列化特点
- 紧凑:高效的使用存储空间
- 快速:读写数据的额外开销小
- 可扩展:随着通信协议的升级而可升级。
- 互操作:支持多语言的交互
Java基本类型与Hadoop常用序列化类型
Java基本类型 | Hadoop Writable类型 |
---|---|
boolean | BooleanWritable |
byte | ByteWritable |
int | IntWritable |
float | FloatWritable |
long | LongWritable |
double | DoubleWritable |
String | Text |
map | MapWritable |
array | ArrayWritable |
自定义bean对象实现序列化接口(Writable)
- 在实现业务时,常用的基本序列化类型又是不能满足所有需求,比如在Hadoop框架内部传递一个bean对象,那么该对象就需要实现序列化接口
- 具体实现bean对象序列化步骤包括
- 必须实现Writable接口
- 反序列化时,需要反射调用空参构造函数,所以必须有空参构造
- 重写序列化方法write
- 重写反序列化方法readFields
- 注意反序列化的顺序和序列化的顺序完全一致
- 要想把结果显示在文件中,需要重写toString(),可用”\t”分开,方便后续用
- 如果需要将自定义的bean放在key中传输,则还需要实现Comparable接口,因为MapReduce框中的Shuffle过程要求对key必须能排序