MapReduce2

一、自定义输入格式

1.自定义类,继承FileInputFormat
2.提供RecordReader
(1)initliaze(InputSplit split, TaskXXXContext context):会在读取切片数据之前提前被框架调用。 InputSplit split:当前读取的切片
TaskXXXContext context:当前Job的上下文,可以通过context获取Job的配置对象。
(2)boolean nextKeyValue():负责从切片中读取一对key-value,读到之后,返回true,否则返回false
被Mapper的run()
setUp();
while(rr.nextKeyValue()){
map(rr.currentKey(),rr.currentValue(),context);
}
(3)设置自定义的输入格式:Job.setInputFormatClass();

二、SequenFile

1.SequenceFile是Hadoop提供的一种文件格式,相比纯文本格式,格式紧凑!保存的是key-value键值对!
2.在Job中将Reducer输出的key-value保存到SequenceFile中 ,可以使用SequenceFileOutPutFormat
3.在Job中读取的数据存放在SequenceFile中,可以使用SequenceFileInputFormat
三、MapTask中的shuffle过程
1.阶段定义:
MapTask:map---------sort
map:Mapper.map()中将输出的key-value写出之前
sort:Mapper.map()中将输出的key-value写出之后
2.sort
(1)当在map()将输出的key-value写出后,记录是会被Partitionner计算一个分区号
(2)计算后,记录会被收到一个缓冲区(MapOutPutBuffer)
(3)收集线程负责向缓冲区收集数据,缓冲区初始值为100M,当使用到80%的阈值,唤醒溢写线程,溢写线程会将缓冲区已经收集的数据溢写到磁盘
(4)在溢写前,会对缓冲区中的数据进行排序(快速排序),在排序时,只通过比较key进行排序
(5)排序后,按照分区,依次将数据写入到磁盘的临时文件的若干分区中
(6)每次溢写都会生成一个临时文件,当所有数据都溢写完成后,会将所有文件片段合并为一个总的最终文件
(7)在合并时,将所有临时文件的相同分区数据,进行合并,合并后再对所有的数据进行排序(归并排序)
(8)最终生成一个结果文件,这个文件分为若干分区,每个分区的数据已经按照key进行了排序,等待ReduceTask的shuffle线程来拷贝数据!

例子

orderid pid acount
10000001 Pdt_01 222.8
10000002 Pdt_06 722.4
10000001 Pdt_02 222.8
10000001 Pdt_05 25.8
10000003 Pdt_01 232.8
10000003 Pdt_01 33.8
10000002 Pdt_04 122.4
10000002 Pdt_03 522.8

统计同一笔订单中,金额最大的商品记录输出
分析得出: 在同一笔订单中,对每条记录的金额进行降序排序,最大的排前边

①orderid和acount属性都必须作为key
②针对key,提供compareTo(),先按照orderid排序(升降序都可以),再按照acount(降序)排序

Mapper
keyin-valuein
map()
keyout-valueout

shuffle之后的数据:
10000001 Pdt_02 222.8
10000001 Pdt_01 222.8
10000001 Pdt_05 25.8

10000002 Pdt_06 722.4
10000002 Pdt_03 522.8
10000002 Pdt_04 122.4

10000003 Pdt_01 232.8
10000003 Pdt_01 33.8

进入Reduce
获取分组比较器,如果没设置默认使用MapTask排序时key的比较器!
默认的比较器比较策略不符合要求,它会将orderId一样且acount一样的记录才认为是一组的!

自定义分组比较器,只按照orderId进行对比,只要OrderId一样,认为key相等,这样可以将orderId相同的分到一个组!
在组内去第一个最大的即可!

Reducer
keyin-valuein
reduce()
keyout-valueout

四、分区

1.分区是在MapTask中通过Parttitioner来计算分区号
2.Partitioner的初始化
(1)计算总的分数partitions,取决于用户设置的ReduceTask的数量
(2)partitions>1 ,默认获取用户设置的Paritionner,如果用户没有定义,那么会使用HashPartitioner. HashPartitioner根据key的hashcode进行计算,相同的key以及hash值相同的key会分到一个区.
(3)patitions<=1,默认初始化为一个Patitionner,这个Patitioner计算的所有的区号都为0.
3.注意
通常在Job的设置中,希望将数据分为几个区,就设置reduceTask的数量为对应的数量!patitions=设置的ReduceTask的数量,0<=分区器计算的区号<patitions

五、排序

1.排序是MR框架在shuffle阶段自动进行
2.在MapTask端发生两次排序,在排序时,用户唯一可以控制的是提供一个key比较器
3.设置key比较器
(1)用户可以自定义key比较器,自定义比较器必须是一个RawComparator类,重点是实现compare()方法
(2)用户可以通过key,让key实现WritableCompare接口,系统自动提供一个比较器,重点是实现compare()方法
4.排序的分类
全排序:对所有的数据进行排序,指生成一个结果文件,这个结果文件整体有序
部分排序:最终生成N个结果文件,每个文件内部整体有序
二次排序:在对key进行比较时,比较的条件为多个
辅助排序:在进行reduce阶段时,通常比较key是否相同,将相同的key分为1组

六、分组

1.分组通过分组比较器,对进入reduce的key进行对比,key相同的分为一组,一次性进入Reducer,被调用reduce()方法
2.分组比较器的设置:
(1)用户可以自定义key的分组比较器,自定义的分组比较器必须是一个RawComparator的类,重点是实现compareTo()方法
(2)如果没有设置key的分组比较器,默认采取在Map阶段排序时,key的比较器
3. Reduce的细节:在进入reduce(),Reducer会自动实例化一个key,value,这个key-value在Redcuer工作期间,一直是一个不变的对象,每次迭代,reducer会把读到的新的key-value的属性值赋值给key-value!
七、Combiner
1.Combiner的本质是一个Reducer,对key-value进行合并
2.Combiner 和 Reducer的区别:Combiner在shuffle阶段运行 ,Reducer在reduce阶段运行
3.Combiner适用于 +,-操作,不适合 *,/操作
4. Combiner的运行时机
在MapTask端: ①每次从缓冲区将数据溢写到磁盘之前,如果设置了Combiner,数据会被Combine之后,再溢写到磁盘!
②在MapTask最后的merge阶段,如果溢写的片段数据>=3,,如果设置了Combiner,在生成
最终的数据时,也会先执行Combine之后再溢写到磁盘
在ReduceTask端: ③shuffle线程从多个MapTask读取同一个分区的数据,之后进行合并,在合并时,如果shuffle所使用的内存不够,也会将部分数据临时溢写到磁盘,此时如果设置了Combiner,数据会被Combine之后,再溢写到磁盘
5. Combiner的本质目的是为了减少MR在运行期间的磁盘IO和网络IO

七、Zookeeper的安装

1.简介
(1)Zookeeper是java编写的一个开源的分布式的存储中间件
(2)Zookeeper可以用来存储分布式系统中各个进程都关心的核心数据!
(3)Zookeeper采用观察者模式 设计,可以运行客户端在读取数据时,设置一个观察者,一旦这个观察的节点触发了指定的事件,服务端会通知客户端线程,客户端可以执行回调方法,执行对应的操作!
(4)Zookeeper=文件系统+通知机制
2.数据结构
在Zookeeper中每个存储数据的基本单位称为znode,每个znode都有一个路径标识,还可以保存byte[]类型的,这个数据默认为1M.
所有的znode都挂载在 / 节点上
3.安装
(1)必须保证环境变量有JAVA_HOME
(2)解压,后配置conf/zoo_cfg文件,配置dataDir=非 /tmp目录即可
(3)集群模式,需要将集群中所有的zk实例进行配置
(4)如果是集群模式,需要在dataDir中,配置myid文件,myid中需要编写zk的serverid
4.使用
启动:bin/zkServer.sh start
bin/zkCli.sh -server host:port
停止:bin/zkServer.sh stop bin/zkCli.sh -server host:port
5.常用的命令
增:create【-s】 【-e】path data
-s :创建一个带序号的znode
-e:创建一个临时znode,临时的znode被所创建的session拥有,一旦session关闭,临时节点会被删除、
删:delete path
rmr path:递归删除
改:set path data
查:get path
stat path
ls path
ls2 path
6.支持四字命令
7.设置观察者
get path watch :监听指定节点数据的变化
ls path watch :监听当前路径子阶段数据的变化,一旦新增或删除了子节点,会触发事件
注意:观察者在设置后,只有当次有效
8.ZK集群的注意事项
(1)ZK在设计时,采用了paxos协议设计,这个协议要求,集群半数以上服务实例存储,集群才能正常提供服务
(2)ZK集群中,server有leader和follower两种角色。leader只有一个,在集群启动时,自动选举产生!
(3)在选举leader时,只有数据和leader保持同步的follower才有权参与竞选leader,在竞选时,serverID大的server有优势!
(4)集群模式ZK的写流程
①客户端可以任意连接zk实例,向server发送请求写命令
②如果当前连接的server不是leader,server会将写命令发送给leader
③leader将写命令广播到集群中的其它节点,所有节点都执行写操作命令!
④一旦集群中半数以上的节点写数据成功,leader会响应当前server,让当前server响应客户端,写操作完成!

八、HadoopHA

1.HA
High Avilable :高可用,意味着必须有容错机制,不能因为集群故障导致不可用!
HDFS:满足高可用
NN:一个集群只有一个,负责接收客户端的请求
DN:一个集群可以启动N个
YARN:满足高可用
RM:一个集群只有一个,负责接收客户端请求
NM:一个集群可以启动N个
实现hadoop的HA,必须保证NN和RM故障,采取容错机制,可以让集群继续使用!
2.防止故障
核心:避免NN和RM单点故障
以HDFS的HA为例:
①NN启动多个进程,一旦当前正在提供服务的NN故障了,让其他的备用的NN继续顶上
②NN负责接受客户端的请求
在接收客户端的写请求时,NN还负责记录用户上传文件的元数据
保证: 正在提供服务的NN,必须和备用的NN之中的元数据必须是一致的!
元数据的同步: ①在active的nn格式化后,将空白的fsimage文件拷贝到所有的nn的机器上
②active的nn在启动后,将edits文件中的内容发送给Journalnode进程
standby状态的nn主动从Journalnode进程拷贝数据,保证元数据的同步
注意: ①Journalnode在设计时,采用paxos协议, Journalnode适合在奇数台机器上启动!
在hadoop中,要求至少需要3个Journalnode进程
②如果开启了hdfs的ha,不能再启动2nn
③当启动了多个NN时,是否允许多个NN同时提供服务?
不允许多个NN同时对外提供服务,因为如果多个NN同时对外提供服务,那么
在同步元数据时,非常消耗性能,而且容易出错!
在同一时刻,最多只能有一个NN作为主节点,对外提供服务!
其余的NN,作为备用节点!
使用active状态来标记主节点,使用standby状态标记备用节点!
3. HDFS HA的搭建步骤
配置:fs.defaltFS=hdfs://slave01:9000
在整个集群中需要启动N个NN,配置N个NN运行的主机和开放的端口!
配置Journalnode
启动:先启动Journalnode
格式化NN,格式化后的fsimage文件同步到其它的NN
启动所有的NN,需要将其中之一转化为active状态
九、压缩
1.压缩的目的:
压缩的目的是MR运行期间,提高MR运行的效率
压缩可以减少MR运行期间的磁盘IO和网络IO
压缩的原则:
IO密集型,多用压缩
计算密集型,CPU负载过重,少用压缩!
3.hadoop支持的压缩格式
默认:deflate,bzip2,gzip
额外安装的:lzo,snappy
特点:bzip2压缩比最高,压缩速度最慢
snappy压缩速度最快,压缩比凑合
deflate,gzip折中
使用便利性:LZO压缩格式最麻烦!①额外安装LZO压缩格式
②如果JOB输入目录中的文件为LZO压缩格式,需要为每个文件创建索引
如果不创建索引,那么输入的文件无法切片,整个文件作为1片
还需要使用LZO特定的输入格式,使用LZOInputFormat!
其他的压缩格式,和纯文本文件使用一致的,不需要额外设置!

可切片的角度:
如果Job的输入采用了以下压缩格式,只有以下格式支持切片!
只有zip2和lzo可以切片!
使用场景:
bzip:对速度没有要求,常用reduce输出结果的压缩格式!
Lzo:作为Job输入文件的压缩格式!
Snappy:作为shuffle阶段的压缩格式!
Mapper运算结束后,需要向磁盘500M的数据,没有用压缩之前,写的速度100M/s
采用了Snappy压缩,需要向磁盘溢写500M的数据,采用了snappy压缩,写的速度100M/s,500M—>300M
Reduce拷贝300M的数据----> 解压缩(速度很快,解压缩消耗的时间可以忽略不计)------>
压缩的考虑:

①Mapper的输入: 主要考虑每个文件的大小,如果文件过大,需要使用可以切片的压缩格式!
②Reducer的输出: reducer的输出主要考虑,输出之后,是否需要下一个Job继续处理!
单个reducer输出的结果的大小!
如果需要被下个Job继续处理,且单个文件过大,也要使用可以切片的压缩格式!

③shuffle阶段: 速度快即可

压缩的参数:
io.compression.codecs : 代表整个Job运行期间,可以使用哪些压缩格式!
配置这个参数后,配置的压缩格式会被自动初始化!
默认值: deflate,gzip,bzip2
mapreduce.map.output.compress: map阶段输出的key-value是否采用压缩
默认值: false
mapreduce.map.output.compress.codec: map阶段输出的key-value采用何种压缩
默认值: deflate
mapreduce.output.fileoutputformat.compress: job在reduce阶段最终的输出是否采用压缩
默认值: false
mapreduce.output.fileoutputformat.compress.codec: job在reduce阶段最终的输出采用何种压缩
默认值: deflate
mapreduce.output.fileoutputformat.compress.type: 如果Job输出的文件以SequenceFile格式!
SequenceFile中的数据,要以何种形式进行压缩!
NONE: 是否压缩及如何压缩取决于操作系统
RECORD(默认): 每个key-value对作为一个单位,压缩一次
BLOCK: SequenceFile中的block,SequenceFile中的block默认为64K,
每个block压缩一次!

二、调度器

  1. FIFO调度器
    FIFO调度器的特点就是单队列,所有的Job按照客户端提交的先后顺序,先到先服务!

     弊端:  如果当前队列中有一个大的Job,非常消耗资源,那么这个Job之后的其他Job都需要付额外的等待时间!
     		造成集群的资源利用率不足!
     		
     解决:   采取多队列的配置
    
  2. 容量调度器
    容量调度器的本质是多个FIFO的队列组成!

     Hadoop默认使用就是容量调度器!
     
     特点: 容量
     			①每个队列可以配置一定的容量,空闲的资源可以匀给其他队列临时使用
     			②可以配置每个job使用的容量的限制,防止一个大的job独占所有资源
     			③可以配置每个用户可以使用的容量限制,防止当个用户占用所有资源
     			
     优点:  ①配置灵活,及时刷新即可、
     		②资源利用率高
     		③安全,可以配置每个队列的访问用户限制
    
  3. 公平调度器
    公平调度器的设置和容量调度器大致相同,也是多条队列,每天队列都可以设置一定的容量!
    每个Job,用户可以设置容量!

     区别: 公平调度器在调度策略上,采用最大最小公平算法,来调度Job,这个算法会保证
     			同一个队列中,所有已经提交,未运行结束的Job,获取到队列中的资源是平等的!
     			
     		导致在一个队列中,小的Job运行有优势,大的Job可能不能及时获取到必须的所有资源,但是不至于饿死!
     		
     当前队列A : 目前有20个CPU,20G 内存...资源
     
     每个Job理论上应该分配  5个CPU, 5G内存,在实际分配资源时,只考虑内存!
     
     队列A中已经提交,未运行的Job:
     
     job1 :  2 个MapTask   2 CPU,2G 内存
     		2 个ReduceTask   1 CPU,1G 内存
     		
     job2 : 2 个MapTask   4 CPU,2G 内存
     		2 个ReduceTask   2 CPU,2G 内存
     		
     job3  :  1 个MapTask   1 CPU,1G 内存
     		1 个ReduceTask   1 CPU,1G 内存 
     		
     job4 : 4 个MapTask   4 CPU,2G 内存
     		4 个ReduceTask   2 CPU,2G 内存
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值