启动hadoop系统,使用sbin/strat-all.sh命令时,请给出启动顺序
namenode --> datanode --> secondarynamenode --> resourcemanager -->nodemanager
大数据的四特性 4v
1.数据量大
2.数据类型多
3.商业价值高
4.处理速度快
hadoop是什么,作用是什么,适用于什么场景
--1.hadoop是什么?
hadoop是由java编写的,在分布式服务器集群上存储海量数据并运行分析引用的开源框架,其核心部件是HDFS和MApReduce,yarn
--2.作用是什么?
1.大数据存储:分布式存储
2.分析海量数据的工具
3.ETL:数据抽取到oracle,mysql,DB2,mongdb,redis,及主流数据库
--3.使用场景?
1.实时日志处理分析 -Flume+Logstash+Kafka +Spark+Streaming
2.数据挖掘:目前比较流行的广告推荐
3.数据支持一次写入,多次读取
4.使用Hbase做数据分析
hadoop的优势有哪些方面?
1.高可靠性:hadoop底层维户多个数据副本
2.高扩展性:在集群间分配任务数据
3.高效性:在mapreduce的思想下hadoop是并行工作的,加快任务处理速度
4.高容错性:能够自动将失败的任务重新分配
hadoop的组成
1.YARN
另一种资源协调者,是hadoop的资源管理器
YARN的任务概述
任务所需要的资源:比如内存,cup,硬盘,网络等都是由YARN管理
2.MapReduce
MapReduce将计算过程分为两个阶段:Map和Reduc
map阶段进行处理输入数据
reduce阶段对map的结果进行汇总计算结果
3.HDFS
是一个文件系统,用于存储文件,通过目录树来定位文件,其次它是分布式的
使用场景:一次写入,多次读取
HDFS的优缺点
优点:
高容错性:能够自动将失败的任务重新分配
数据规模:适合处理大数据.
文件规模:能够处理百万规模以上的文件规模.
缺点:
不适合低延时的数据访问.
无法高效的对小文件进行存储.
不支持并发写入和文件随机修改.
HDFS的文件块大小
hdfs中的文件在物理上是分块存储的,块的大小可以通过配置值参数来规定默认是128M,
--为什么快的大小不能设置太大,也不能设置太小?
1.设置太小,会增加寻址时间
2.设置太大,从磁盘传输数据的时间会明显的大于定位这个块开始位置所需的时间,导致处理数据时过慢
总结:HDFS的块大小取决于磁盘传输率.
MapReduce的Shuffle阶段
一.MapTsk阶段五个步骤
1.read阶段:提交job任务,附带三个信息(切片信息,jar包信息,以及xml信息),去开启相应数量的MapTask读取文件
2.map阶段:系统默认的方式是TextInputFormat,通过去读行来切割数据,以便后续的数据处理(可以自定义代码进行数据处理).
3.collect阶段:map结束之后将切割完得数据输送到环形缓冲区分区和排序系统默认按照key排序,按字典顺序排序,(排序方式是快排).
4.溢写阶段:就是当环形缓冲区数据达到起大小的80%是开始溢出(默认大小是100M),将数据写入到磁盘.
5.combiner:将数据归并,在适当的时候使用combiner,可以减少网咯传输数据量,优化hadoop
的框架性能.
二.ReduceTask4阶段
1.coyp阶段:通过远程数据拷贝方式,从MapTask中拷贝已经处理好的数据到内存(注意.MpaTask和ReduceTask很大程度上不是在同一台服务器上,这就是需要进行序列化和反序列化(bean对象)).
2.Meage阶段:合并阶段,将拷贝过来的多个小文件合并成一个大文件,到达到内存数据量的阈值时(阈值就是内存),会自动将数据写入磁盘.
3.sort阶段:按照某种需求将数据写入磁盘,与meger同时进行.
4.reduce阶段:将数据写入到指定的分区文件中.
--修改版
1.map方法之后reduce方法之前这段处理过程叫做Shuffle
2.mpa方法之后,数据首先进入到分区方法,把数据标记好分区,然后把数据发送到环形缓冲区,环形缓冲区默认大小是100m,环形缓冲区 达到80%时,进行溢写,溢写前对数据进行排序,排序按照对key的索引进行字典顺序排序,排序的手段快排,溢写产生大量的溢写文件,需要对溢写文件进行归并排序,对溢写文件也可以进行cimbiner操作,前提是汇总操作,求平均值不行,最后文件按照分区存储到磁盘,等待reduce端拉取
3.每个reduce拉取map端对应分区的数据,拉取数据后行先存储到内存中,内存不够了,在存到磁盘中,拉取完所有数据后,采用归并将内存和磁盘的数据都进行排序,在进入reduce方法前,可以对数据进行分组操作.
mapreduce 中的数据倾斜
--什么是数据倾斜?
简单来说数据倾斜就是数据的key 的分化严重不均,造成一部分数据很多,一部分数据很少的局面。
--数据倾斜的解决方案
1.hive.map.aggr=true:在map中会做部分聚集操作,效率更高但需要更多的内存。
2.hive.groupby.skewindata=true:数据倾斜时负载均衡,当选项设定为true
3.增加reduce 的jvm内存,增加reduce 个数
HDFS的读写流程
一.hdfs写数据的过程
1.向namnode请求上传文件/opt/data/1.txt
2.1检查目录是否可以创建文件
2.2检查权限
2.3检查目录结构(目录是否存在)
2.响应可以上传(响应给客户端)
3.请求上传第一个block(0-128M),请返回datanode
4.返回d1,d2,d3,表示采用这三个节点存储数据(返回给客户端)
5.请求建立bolck通道(这个通道会一直通到d3)
6.每个datanode答应成功
7.客户端开始往d1上传block(先从磁盘读取放到本地内存缓存),以packet(64k)为单位,d1收到一个packet就会传给d2,d2就会传给d3,d1每个packetd会放入一个应答队列等待答应
8.当一个block传输完成之后,客户端再次请求namenode上传第二个bolck的服务器(重复执行3-7部)
二,hdfs的读数据过程
1.向namenode请求下载文件
2.1检查权限
2.2检查文件block列表
2.3选出每个block的对应主机列表
3.返回主机列表给客户端
4.和每个block所在的主机建立管道(就近原则,然后在随机)
5.开始数据的读取(读取的单位packet:64K)
6.将每个block合并成一个完整的文件
MapReduce的优缺点
一.优点
1.MapReduce易于编程
他简单的实现一些接口就可以完成一个分布式程序
2.良好的扩展性
可以通过简单的新增机器来扩展它的计算能力
3.高容错性
比如一台机器挂了,他可以把上面的计算任务转义到另外一个节点上运行,不至于这个任务失败
4.适合PB级别的海量数据的处理
二,缺点
1.不擅长实时计算
MapReduce无法象mysql一样在毫秒或者秒级内返回结果
2.不擅长流式计算
流式计算的数据是动态输入的,二MapReduce的数据级是静态的
3.不擅长DAG(有向无环图)计算
每个mapreduce作业的输出结果都会写入到磁盘,会造成大量的磁盘IO,导致性能非常的低
1.hadoop的介绍
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BMo5VL97-1623596660206)(…/TypoarWrokPath/images/1614482244682.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jQM5qhyD-1623596660208)(…/TypoarWrokPath/images/1614482839596.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-28x5IsHN-1623596660210)(…/TypoarWrokPath/images/1614483032212.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LbHCDieg-1623596660212)(…/TypoarWrokPath/images/1614483089268.png)]
2.hadoop1.x的架构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nPMMpeNO-1623596660215)(…/TypoarWrokPath/images/1614484024045.png)]
1.图解
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xZPhTr6R-1623596660215)(…/TypoarWrokPath/images/1614484072621.png)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QdumDd1C-1623596660217)(…/TypoarWrokPath/images/1614484770403.png)]
3.hadoop2.x架构
Namenode单节点和ResourceManager单节点模型
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NyR4edAk-1623596660218)(…/TypoarWrokPath/images/1614485476949.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P6JIS3eT-1623596660219)(…/TypoarWrokPath/images/1614485520231.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SmAfEhed-1623596660219)(…/TypoarWrokPath/images/1614485453863.png)]
Namenode单节点和ResourceManager高可用模型
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xH1Hr6hu-1623596660220)(…/TypoarWrokPath/images/1614487281891.png)]
Namenode高可用和ResourceManager单节点模型
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5B45XJv4-1623596660221)(…/TypoarWrokPath/images/1614487450461.png)]
Namenode和RescourceManager都实现高可用(最理想)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CJwk8gLu-1623596660222)(…/TypoarWrokPath/images/1614487583162.png)]
4.安装hadoop的环境准备
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-onKg3aPl-1623596660223)(…/TypoarWrokPath/images/1614487694097.png)]
5.配置集群
#每台虚拟机都需要配置
vim /etc/profile
export HADOOP_HOME=/opt/hadoop
export PATH=:$HADOOP_HOME/bin:$HADOOP_HOME/sbin:$PATH
bin/hdfs namenode -format
6.集群规划
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jG9KvfbQ-1623596660223)(…/TypoarWrokPath/images/1614751508812.png)]
7.集群分发
解压hadoop的压缩文件 解压 (注意注意注意名字不要去hadoop)
然后配置文件hadoop2.7.5下面etc/hadoop的配置文件
然后使用shell脚本创建文件夹 vim a.sh
mkdir -p /opt/hadoop-2.7.5/hadoopDatas/tempDatas
mkdir -p /opt/hadoop-2.7.5/hadoopDatas/namenodeDatas
mkdir -p /opt/hadoop-2.7.5/hadoopDatas/namenodeDatas2
mkdir -p /opt/hadoop-2.7.5/hadoopDatas/datanodeDatas
mkdir -p /opt/hadoop-2.7.5/hadoopDatas/datanodeDatas2
mkdir -p /opt/hadoop-2.7.5/hadoopDatas/nn/edits
mkdir -p /opt/hadoop-2.7.5/hadoopDatas/snn/name
mkdir -p /opt/hadoop-2.7.5/hadoopDatas/dfs/snn/edits
需要回到需要拷贝文件的当前父目录
scp -r hadoop node01:$PWD
scp -r hadoop node02:$PWD
对主节点node01的hadoop2.7.5 namenode 进行格式化
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5XYbq8CD-1623596660224)(…/TypoarWrokPath/images/1614753489603.png)]
8.启动集群
8.1进群重新格式化解决方法
1.停掉集群
2.删除 节点 node01 hadoopDatas 目录 删除node02 hadoopDatas 删除node03 hadoopDatas
3.在执行格式化命令 bin/hdfs namenode -format
sbin/start-dfs.sh #启动成功
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EUeHQyuh-1623596660225)(…/TypoarWrokPath/images/1614685208745.png)]
nod02
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GNuW2ilq-1623596660226)(…/TypoarWrokPath/images/1614759174719.png)]
node03
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jkqyKMMP-1623596660227)(…/TypoarWrokPath/images/1614759199890.png)]
9.启动yarn
sbin/start-yarn.sh 启动成功
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K5CGvUFW-1623596660227)(…/TypoarWrokPath/images/1614759535793.png)]
10.启动日志
sbin/mr-jobhistory-daemon.sh start historyserver 启动成功
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mzXAOxTy-1623596660229)(…/TypoarWrokPath/images/1614759754703.png)]
如果需要使用node01 node02 node03 进行访问的话就是需要在本机的windows/system.2/drivec/etc/host.ics 中映射ip地址
c:windows/sytem32/drivers/etc/host.ics
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PkHcG7Dr-1623596660230)(…/TypoarWrokPath/images/1614759939438.png)]
查看hdfs
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LMZToVCz-1623596660231)(…/TypoarWrokPath/images/1614760440353.png)]
查看yarm集群
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IXLfOFYD-1623596660232)(…/TypoarWrokPath/images/1614760686465.png)]
查看JobHistory
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x98VvMmJ-1623596660232)(…/TypoarWrokPath/images/1614760667005.png)]
11.Hadoop核心–HDFS
1.概述
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I1PDjAAd-1623596660233)(…/TypoarWrokPath/images/1614762306288.png)]
分布式文件系统思维导图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4gJU9gYG-1623596660234)(…/TypoarWrokPath/images/1614762578245.png)]
2.HDFS应用场景
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZeO0As6w-1623596660235)(…/TypoarWrokPath/images/1614762676920.png)]
3.HDFS不适应的场景–牺牲延时
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BYFMZM3C-1623596660236)(…/TypoarWrokPath/images/1614763106952.png)]
12.HDFS的架构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-immtMky7-1623596660237)(…/TypoarWrokPath/images/1614763544496.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mYqP6fG1-1623596660238)(…/TypoarWrokPath/images/1614763629277.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6PBUwvl1-1623596660239)(…/TypoarWrokPath/images/1614764021075.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LuB4n3tz-1623596660239)(…/TypoarWrokPath/images/1614764029806.png)]
13.Namenode的作用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sWReUE0x-1623596660240)(…/TypoarWrokPath/images/1614764482717.png)]
1.namenode元数据信息
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C3bikQmd-1623596660241)(…/TypoarWrokPath/images/1614765161755.png)]
14.Datanode的作用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Qlt70GKx-1623596660242)(…/TypoarWrokPath/images/1614776906846.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j4MdTp7U-1623596660250)(…/TypoarWrokPath/images/1614782193584.png)]
Data Name 的缓存数据块
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l2o84HDb-1623596660252)(…/TypoarWrokPath/images/1614782178990.png)]
15.hadoop的副本机制和机架感知
1.副本机制
1.有多个副本(block)的意义 hadoop1.x的版本block的默认最大内存是168M 在hadoop2.x的版本block的默认最大内存是128M
2.副本的多可以去hadoop2.7.5的etc hadoop hdfs-site.xml里面进行设置
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-peaQbY3J-1623596660253)(…/TypoarWrokPath/images/1614782991608.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5iW9gJBk-1623596660254)(…/TypoarWrokPath/images/1614783369466.png)]
3.案列如果一个文件有300M那么怎么分(某中意义上来讲block是个逻辑单位)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-azFdMXnk-1623596660255)(…/TypoarWrokPath/images/1614783236621.png)]
2.机架感知
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ryEVAq9f-1623596660256)(…/TypoarWrokPath/images/1614783946232.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dvLUMbKZ-1623596660256)(…/TypoarWrokPath/images/1614783922832.png)]
16.HDFS命令行的使用
#ls
格式:hdfs dfs -ls URI #URL表示需要展示的文件夹路径
作用:类似于Linux的ls命令 显示文件夹列表
#lsr
格式:老版本hdfs dfs -lsr URI 新版本 hdfs dfs -ls -R URL #URL表示需要展示的文件夹路径
作用: 在整个目录下递归执行ls
#mkdir
格式:hdfs dfs -mkdir [-p] URI #URL表示需要展示的文件夹路径
作用创建目录
#put
格式:hdfs dfs -put 本地路径+文件名 需要上传到哪里的路径 #URL表示需要展示的文件夹路径
作用:文件的拷贝 也可以从标准输入中读取输入,写入目标文件里
#du c查看文件的大小 以B为单位
hdfs dfs -du [-s] [-h] /employee/employee.txt
#text 查看文件内容
hdfs dfs -text 文件路径
#stat
hdfs dfs -stat "%b %r %o" /aa/abc.txt
%b 文件大小 %r 打印备份数 %o 打印块大小
1.moveFromLocal
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hbjZte1P-1623596660257)(…/TypoarWrokPath/images/1614785704307.png)]
2.get 只做拷贝
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dk6ZYRyK-1623596660258)(…/TypoarWrokPath/images/1614786103807.png)]
2.mv 不能夸系统 url文件路径 dest 目标位置[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mOXwpAXG-1623596660259)(…/TypoarWrokPath/images/1614788598079.png)]
3.rm 删除之后会自动在根目录下面创建一个user目录
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CaadqVy7-1623596660260)(…/TypoarWrokPath/images/1614788827747.png)]
4.cp 拷贝
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CwZa8ie0-1623596660260)(…/TypoarWrokPath/images/1614835486736.png)]
5.cat
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BEaHp3wH-1623596660262)(…/TypoarWrokPath/images/1614836162223.png)]
6.chmod 权限的更改
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FyKZA2DZ-1623596660263)(…/TypoarWrokPath/images/1614836297300.png)]
7.chown
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7dfLEZJE-1623596660264)(…/TypoarWrokPath/images/1614836943345.png)]
8.appendToFile[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8uGNrBlO-1623596660265)(…/TypoarWrokPath/images/1614837237814.png)]
17.HDFS的高级使用命令
1.HDFS文件限额配置
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5gwH5CdG-1623596660265)(…/TypoarWrokPath/images/1614837590187.png)]
1.数量限额
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q3ytYEio-1623596660266)(…/TypoarWrokPath/images/1614839728190.png)]
2.空间大小限额 在给目录设置大小的时候必须是blcok size的三倍 128M * 3
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kGOX7Bk4-1623596660267)(…/TypoarWrokPath/images/1614841028234.png)]
问题:如果一个文件有129M 目录需要设置多大才能把 文件上传上去?
129M的文件在一台机器上面会被切成两个block
但是有三台机器创建副本,所以就是 128乘2乘3 M 才可以把文件上传上去
18.HDFS 的安全模式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BpL9Q4iS-1623596660268)(…/TypoarWrokPath/images/1614843764497.png)]
1.副本率
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KnEdQAyv-1623596660269)(…/TypoarWrokPath/images/1614844182674.png)]
2.安全模式操作命令
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VhMZ2ayA-1623596660270)(…/TypoarWrokPath/images/1614844549140.png)]
19.HDFS的基准测试
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZdTw80U0-1623596660270)(…/TypoarWrokPath/images/1614846792011.png)]
#测试写入数据
hadoop jar /opt/hadoop-2.7.5/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-2.7.5.jar TestDFSIO -write -nrFiles 10 -fileSize 10MB
#测试读数据
hadoop jar /opt/hadoop-2.7.5/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-2.7.5.jar TestDFSIO -read -nrFiles 10 -fileSize 10MB
#清除数据
hadoop jar /opt/hadoop-2.7.5/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-2.7.5.jar TestDFSIO -clean
20HDFS的文件写入过程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-awZGUiHZ-1623596660271)(…/TypoarWrokPath/images/1614953776043.png)]
21.HDFS的读取过程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ARpBmXiI-1623596660272)(…/TypoarWrokPath/images/1614954996653.png)]
HDFS的元数据辅助管理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-89MbktGQ-1623596660273)(…/TypoarWrokPath/images/1614958350495.png)]
1.查看fsimage的文件命令 路径 cd /hadoop2.7.5/dadoopDatas/namenodeDatas/current 里面
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-diAe4Fkh-1623596660274)(…/TypoarWrokPath/images/1614956826804.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-thYmYIAK-1623596660274)(…/TypoarWrokPath/images/1614956474199.png)]
执行完 就会在目录下面产生一个.xml的文件
2.查看edtis的文件 cd /hadoop2.7.5/dadoopDatas/nn/edtis/current
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qhCYZuPr-1623596660277)(…/TypoarWrokPath/images/1614957003895.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2v8icCCK-1623596660277)(…/TypoarWrokPath/images/1614957060349.png)]
里面放的都是操作日志的文件
3.小总结
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TADVAE58-1623596660279)(…/TypoarWrokPath/images/1614958116664.png)]
22.SecondaryNameNode
如何辅助管理fsimage 与edits文件?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9PVKVga8-1623596660279)(…/TypoarWrokPath/images/1614958269277.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dFU5GpNy-1623596660281)(…/TypoarWrokPath/images/1614958868345.png)]
这样子namenode的压力就会减小
1.SecondaryNameNode合并edits和fsimage的过程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NkbZOxjd-1623596660282)(…/TypoarWrokPath/images/1614959041185.png)]
23.windows下面配置hadoop环境
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zz0Me7JO-1623596660283)(…/TypoarWrokPath/images/1614992655416.png)]
24.获取FileSystem的四种方式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fxpgVWHX-1623596660284)(…/TypoarWrokPath/images/1614998432396.png)]
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>3.1.3</version>
</dependency>
/**
* Configuration 该类的对象封装了客户端或者服务器的配置
* FileSystem 该类的对象是一个文件系统对象,可以使用该类对象的一些方法来对文件进行操作,通过FileSyatem
* 的静态方法get获得该对象
**/
//获取FileSystem的集中类型
//第一种
@Test
public void FileSystemdemo01() throws IOException {
Configuration configuration = new Configuration();
//指定使用的文件系统类型
//fs.defaultFS 固定不变的参数
configuration.set("fs.defaultFS", "hdfs://node01:8020/");
//获取指定的文件系统
//导包注意 import org.apache.hadoop.fs
FileSystem fileSystem = FileSystem.get(configuration);
System.out.println("demo01-->" + fileSystem);
}
//第二种
@Test
public void FileSystemdemo02() throws Exception {
FileSystem fileSystem = FileSystem.get(
new URI("hdfs://node01:8020")
, new Configuration()
);
System.out.println("demo02-->" + fileSystem);
}
//第三种
@Test
public void FileSystemdemo03() throws IOException {
Configuration configuration = new Configuration();
//指定文件系统
configuration.set("fa.defaultFS", "hdfs://node01:8020");
//创阿FileSystem的实列
FileSystem fileSystem = FileSystem.newInstance(configuration);
System.out.println("demo03-->" + fileSystem.toString());
}
//地四种
@Test
public void FileSystemdemo04() throws Exception {
FileSystem fileSystem = FileSystem.newInstance(
new URI("hdfs://node01:8020")
, new Configuration());
System.out.println("demo04-->" + fileSystem);
}
使用url访问数据
//1.错误1
/**
* 是maven加载hadoop的依赖包之后,启动项目出现了以上异常
* 这个异常是jar包的冲突,删除掉slf4j-log4j12-1.7.26.jar就可以了
* 我们在maven依赖中对hadoop-hdfs和hadoop-client的依赖都去除slf4j-log4j12依赖即可
*/
@Test //使用url方式访问数据
public void demo01() throws IOException {
//1.注册hdfs的url
URL.setURLStreamHandlerFactory(new FsUrlStreamHandlerFactory());
//2.获取文件输入流
InputStream inputStream = new URL("hdfs://node01:8020/dir1/a.txt").openStream();
//3.获取文件输出流
FileOutputStream fileOutputStream = new FileOutputStream(new File("D:/a.txt"));
//4.实现文件的拷贝
IOUtils.copy(inputStream, fileOutputStream);
//5.关闭流
System.out.println("完成");
org.apache.commons.io.IOUtils.closeQuietly(inputStream);
org.apache.commons.io.IOUtils.closeQuietly(fileOutputStream);
}
HADOOP API 操作
//遍历hdfs中的所有文件
@Test
public void mylistFile() throws Exception {
//获取FileSystem
FileSystem fileSystem = FileSystem.newInstance(
new URI("hdfs://node01:8020"),
new Configuration());
//获取RemoteIterator(迭代器) 得到所有的文件夹 第一个参数指定要遍历的路径,第二参数指定是否递归遍历
RemoteIterator<LocatedFileStatus> fileStatusRemoteIterator =
fileSystem.listFiles(new Path("/"), true);
while (fileStatusRemoteIterator.hasNext()) {
//获取文件
LocatedFileStatus next = fileStatusRemoteIterator.next();
//获取block信息
BlockLocation[] blockLocations = next.getBlockLocations();
System.out.println("block数量-->" + blockLocations.length);
System.out.println("获取文件名字-->" + next.getPath().getName());
System.out.println("获取文件路径-->" + next.getPath().toString());
}
//关闭
fileSystem.close();
}
//hdfs创建文件夹
@Test
public void mkdirdemo() throws Exception {
FileSystem fileSystem = FileSystem.newInstance(
new URI("hdfs://node01:8020"),
new Configuration());
boolean mkdirs = fileSystem.mkdirs(new Path("/aa/bb/cc"));
FSDataOutputStream fsDataOutputStream = fileSystem.create(new Path("/aa/bb/cc/a.txt"));
if (mkdirs) {
System.out.println("创建成功");
}
fileSystem.close();
}
@Test//创建文件
public void mkdirdemo01() throws Exception {
FileSystem fileSystem = FileSystem.newInstance(
new URI("hdfs://node01:8020"),
new Configuration());
//如果输入的路径不存在也会自动创建
fileSystem.create(new Path("/aa/bb/cc/a.txt"));
fileSystem.close();
}
@Test//删除文件或文件夹
public void deletefileandwjj() throws Exception {
FileSystem fileSystem = FileSystem.newInstance(
new URI("hdfs://node01:8020"),
new Configuration());
//删除(删除路径最后面的文件或者文件夹)
fileSystem.deleteOnExit(new Path("/aa/bb/cc"));
fileSystem.close();
}
//文件的下载
@Test
public void FileToLocal() throws URISyntaxException, IOException {
FileSystem fileSystem = FileSystem.newInstance(
new URI("hdfs://node01:8020")
, new Configuration());
//路径是hadoop的路径 通过filesystem的open方法
FSDataInputStream open = fileSystem.open(new Path("/aa/bb/a.txt"));
//上传到本地
FileOutputStream fileOutputStream =new FileOutputStream(new File("D:/aa.txt"));
//一边读取一边上传
IOUtils.copy(open,fileOutputStream);
//关闭流
org.apache.commons.io.IOUtils.closeQuietly(open);
org.apache.commons.io.IOUtils.closeQuietly(fileOutputStream);
//关闭filesystem
fileSystem.close();
}
//文件下载方法二
@Test
public void FileToLocal02() throws URISyntaxException, IOException {
FileSystem fileSystem = FileSystem.newInstance(
new URI("hdfs://node01:8020")
, new Configuration());
fileSystem.copyToLocalFile(new Path("/aa/bb/a.txt"),new Path("D:/bb.txt"));
fileSystem.close();
}
//本地文件上传到hadoop
@Test
public void LocalToFile() throws URISyntaxException, IOException {
FileSystem fileSystem = FileSystem.newInstance(
new URI("hdfs://node01:8020")
, new Configuration());
fileSystem.copyFromLocalFile(new Path("file:///D:/abc.txt"),new Path("/aa"));
fileSystem.close();
}
HADOPP访问权限控制
1.去掉所有权限
hdfs dfs -chmod 000 路径
2.让权限生效
1.停止集群
回到hadoop主目录 执行 sbin/stop-dfs.sh
2.进入 vim hadoop2.7.5/etc/hadoop/hdfs-size.xml 设置为true
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-InLWHJjq-1623596660285)(…/TypoarWrokPath/images/1615041728880.png)]
3.修改另外两台主机的配置文件
3如果没有权限那么就当前用户加可读可写权限
hdfs dfs -chmod 600 /dir1/a.txt
改了权限但是还是会报错,但是是给Linux系统的用户(root)加的权限 但是windows 不是root用户所以还是会报错
解决就是给当前用户和其他用户组都加上权限
hdfs dfs -chmod 666 /dir1/a.txt
4.如果文件只给了读写的权限,那我们可以伪装用户
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7QMAXA7O-1623596660287)(…/TypoarWrokPath/images/1615042942742.png)]
25.HDFS的小文件合并
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r9raETd3-1623596660292)(…/TypoarWrokPath/images/1615043167927.png)]
1.Linux HADOOP小文件合并下载方法
hdfs dfs -getmerge /dir1/*.txt ./ss.txt
2.本地小文件合并上传到Linux的hadoop
//把本地小文件和并成大文件一起上传
@Test
public void bigfiletoLinux() throws Exception{
//获取分布式文件系统
FileSystem fileSystem = FileSystem.get(
new URI("hdfs://node01:8020")
, new Configuration(), "root");
FSDataOutputStream fsDataOutputStream = fileSystem.create(new Path("/dir1/bigfile.txt"));
//获取本地文件系统
LocalFileSystem local = FileSystem.getLocal(new Configuration());
//通过本地文件系统获取文件列表的所有详情,为一个集合
FileStatus[] fileStatuses = local.listStatus(new Path("file:///D://test"));
//遍历这个数组
for(FileStatus fileStatus:fileStatuses){
//获取文件的输入流
FSDataInputStream open = local.open(fileStatus.getPath());
//将小文件复制到大文件
IOUtils.copy(open, fsDataOutputStream);
org.apache.commons.io.IOUtils.closeQuietly(open);
}
org.apache.commons.io.IOUtils.closeQuietly(fsDataOutputStream);
local.close();
fileSystem.close();
}
26HDFS的高可用机制
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f38RWweN-1623596660293)(…/TypoarWrokPath/images/1615045607291.png)]
1.高可用的架构图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6Nqq2YzW-1623596660294)(…/TypoarWrokPath/images/1615045714900.png)]
2.组件介绍
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gjehzCU9-1623596660296)(…/TypoarWrokPath/images/1615045850543.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pY3VYugQ-1623596660297)(…/TypoarWrokPath/images/1615046000522.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UkIB7EZc-1623596660299)(…/TypoarWrokPath/images/1615046008230.png)]
3.元数据的同步
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m7F59WJC-1623596660300)(…/TypoarWrokPath/images/1615046424437.png)]
4.如果namenode宕机了,选举机制
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3KT44Rku-1623596660301)(…/TypoarWrokPath/images/1615049077491.png)]
27.HDFS的联邦机制(Federation)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ybYj4MAM-1623596660302)(…/TypoarWrokPath/images/1615049542378.png)]
28.HADOOP的MapReduce的介绍
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iscF9nk1-1623596660303)(…/TypoarWrokPath/images/1615090253685.png)]
1.mapreduce工作流程图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gPDsZPwT-1623596660304)(…/TypoarWrokPath/images/1615090876268.png)]
29.MapReduce的设计构思
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CBJx2rcf-1623596660305)(…/TypoarWrokPath/images/1615091597153.png)]
1.MapReduce流程图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sc3GWCSx-1623596660306)(…/TypoarWrokPath/images/4-MapReduce编程流程.jpg)]
ResouceManager 进行接收,并且进行任务分配 ,NodeManager执行具体的计算任务
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CVPoK0Np-1623596660307)(…/TypoarWrokPath/images/1615092680430.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WE5jE9HX-1623596660308)(…/TypoarWrokPath/images/1615092577339.png)]
30MapReduce的编程规范
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xOcQOY6i-1623596660309)(…/TypoarWrokPath/images/1615093149482.png)]
31.MapReduce案例
1.准备数据上传到hadoop
2.编写mapper
/*
* KEYIN k1的类型
* VALUEIN v1的类型
* KEYOUT k2的类型
* VALUEOUT v2的类型
* */
//1.继承Mapper
//使用自己的数据类型
public class WordCountMapper extends Mapper<LongWritable, Text,Text,LongWritable> {
//重写map方法,就是将k1和v1转为k2和v2
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
/*
参数解释
key 行偏移量
value 每一行的文本数据
context 表示上下文对象 起到桥梁作用,map执完可以靠context交给shuffle
* */
//1.将一行的文本数据进行拆分
String[] split = value.toString().split(",");
// 2.遍历数组,组装k2,v2 遍历快捷键iter
Text text = new Text();
LongWritable longWritable = new LongWritable();
for (String word : split) {
//3.将k2,v2写入上下文
text.set(word);
longWritable.set(1);
context.write(text,longWritable);
}
}
}
3.编写Reduce
/*
* KEYIN k2的类型
* VALUEIN v2的类型
* KEYOUT k3的类型
* VALUEOUT v3的类型
* */
public class WordCountReduce extends Reducer<Text, LongWritable, Text, LongWritable> {
//将新的k2 v2 转成 k3 v3 将k3 v3 写入上下文中
@Override
protected void reduce(Text key, Iterable<LongWritable> values, Context context) throws IOException, InterruptedException {
/*
key 新的k2
values 集合 新 v2
*context表示上下文对象
* */
//1.遍历集合,将集合中的数字相加,得到v3
long count = 0;
for (LongWritable value : values) {
count += value.get();
}
//2.将k3 v3写入上下文中
context.write(key, new LongWritable(count));
}
}
4.定义主类,秒速job并提交job
public class JobMain extends Configured implements Tool {
//该方法指定一个job任务
@Override
public int run(String[] strings) throws Exception {
//创建一个job对象
//获取下面main方法中的configuration对象
Job job = Job.getInstance(super.getConf(), "wordcount");
//配置job任务对象8个步骤
job.setInputFormatClass(TextInputFormat.class);
//1.指定文件的读取方式和读取路径
TextInputFormat.addInputPath(job,new Path("hdfs://node01:8020/wordcount"));
//2指定mapper阶段的处理方式和数据类型
job.setMapperClass(WordCountMapper.class);
//设置mapper阶段k2的类型
job.setMapOutputKeyClass(Text.class);
//设置mapper阶段的v2的类型
job.setMapOutputValueClass(LongWritable.class);
//3.4.5.6采用默认方式处理 Shuffle
//7,指定Reduce阶段的处理方式和数据类型
job.setReducerClass(WordCountReduce.class);
//设置k3类型
job.setOutputKeyClass(Text.class);
//设置v3类型
job.setOutputValueClass(LongWritable.class);
//8设置输出类型
job.setOutputFormatClass(TextOutputFormat.class);
//设置输出路径
TextOutputFormat.setOutputPath(job,new Path("hdfs://node01:8020/wordcount_out"));
//等待任务结束
boolean b = job.waitForCompletion(true);
return b ?0:1;
}
public static void main(String[] args) throws Exception {
//主要是用于配置信息
Configuration configuration = new Configuration();
//1.启动job任务 返回0 表示执行成功 否则执行失败
int run = ToolRunner.run(configuration, new JobMain(), args);
//退出
System.out.println("退出成功");
System.exit(run);
}
}
32.MapReduce的运行模式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9nBkWcjc-1623596660310)(…/TypoarWrokPath/images/1615103031518.png)]
1.把Java代码导成jar包
33.MapReduce集群运行jar
hadoop-mapreduce-0.0.1-SNAPSHOT.jar idea打成的jar lhh.com.MapReduce.JobMain 主程序JobMain的路径
hdfs -jar hadoop-mapreduce-0.0.1-SNAPSHOT.jar lhh.com.MapReduce.JobMain
1.下载下来运行的结过图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yYsuhAFi-1623596660313)(…/TypoarWrokPath/images/1615109461597.png)]
34.mapReduce的分区
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bHFY7LoP-1623596660314)(…/TypoarWrokPath/images/1615183273385.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eS82K1r1-1623596660315)(…/TypoarWrokPath/images/2-Shuffle阶段-分区 - 副本.bmp)]
1.MapReduce的分区代码
1.PartitionMapper代码
/*
* k1 行偏移量
* v1 每一行的数据
*
* k2 每一行的数据
* v2 使用空占位符,自定义类型
* */
public class PartitionMapper extends Mapper<LongWritable, Text,Text, NullWritable> {
//map方法将k1 v1 转为 k2 v2
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
context.write(value,NullWritable.get());
}
}
2.PartitionReduce代码
public class ParititionReduce extends Reducer<Text, NullWritable,Text,NullWritable> {
@Override //不做作任何处理,将原数据原封不动的输出
protected void reduce(Text key, Iterable<NullWritable> values, Context context) throws IOException, InterruptedException {
context.write(key,NullWritable.get());
}
}
3.MyPartition代码
public class MyPritition extends Partitioner<Text, NullWritable> {
@Override //指定分区规则,返回对应的分区编号
public int getPartition(Text text, NullWritable nullWritable, int i) {
//1.拆分行文本数据(k2),获取中奖字段的值
String s = text.toString().split("\t")[5];
//2.判断中奖之后的值和15的关系,然后返回对应分区编号的值
int i1 = Integer.parseInt(s);
if(i1> 15){
return 1;
}else{
return 0;
}
}
}
4.PaertitionMain代码
public class PartitionMain extends Configured implements Tool {
@Override
public int run(String[] strings) throws Exception {
Job job = Job.getInstance(super.getConf(), "partition_mapreduce");
//八部
job.setJarByClass(PartitionMain.class);
//1.指定文件读取方式和读取路径
job.setInputFormatClass(TextInputFormat.class);
TextInputFormat.addInputPath(job, new Path("hdfs://node01:8020/input"));
//TextInputFormat.addInputPath(job, new Path("file///D:\\Study\\bigdata\\hadoop\\资料-史上最全面的hadoop\\day05资料\\day05\\资料\\partition.csv"));
//2.设置mapper类和数据类型
job.setMapperClass(PartitionMapper.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(NullWritable.class);
//3.4,5.6 分区 排序 规约 分组 shuffle
//3.指定分区类
job.setPartitionerClass(MyPritition.class);
//4.5.6
//7.指定reduce类数据类型和写入路径
job.setReducerClass(ParititionReduce.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(NullWritable.class);
//设置reduce分区的个数
job.setNumReduceTasks(2);
///8.指定输出类和输出路径
job.setOutputFormatClass(TextOutputFormat.class);
// TextOutputFormat.setOutputPath(job, new Path("file:///D:/test01"));
TextOutputFormat.setOutputPath(job, new Path("hdfs://node01:8020/output_mapreduce"));
//等待任务结束
boolean b = job.waitForCompletion(true);
return b ? 0:1 ;
}
public static void main(String[] args) throws Exception {
Configuration configuration = new Configuration();
int run = ToolRunner.run(configuration, new PartitionMain(), args);
System.out.println("程序退出");
System.exit(run);
}
35MapReduce中的计数器
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ccDEr58R-1623596660316)(…/TypoarWrokPath/images/1615267975263.png)]
1.统计Mapper次数
public class PartitionMapper extends Mapper<LongWritable,Text,Text,NullWritable>{
//map方法将K1和V1转为K2和V2
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
//方式1:定义计数器
//第一个参数 定义计数器的类型 第二个参数定义一个名字
Counter counter = context.getCounter("MR_COUNTER", "partition_counter");
//每次执行该方法,则计数器变量的值加1
counter.increment(1L);
context.write(value,NullWritable.get());
}
}
2.统计reduce次数
public class PartitionerReducer extends Reducer<Text,NullWritable,Text,NullWritable> {
public static enum Counter{
MY_INPUT_RECOREDS,MY_INPUT_BYTES
}
@Override
protected void reduce(Text key, Iterable<NullWritable> values, Context context) throws IOException, InterruptedException {
//方式2:使用枚枚举来定义计数器
context.getCounter(Counter.MY_INPUT_RECOREDS).increment(1L);
context.write(key, NullWritable.get());
}
}
36MapReduce的序列化和排序
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yor966ub-1623596660318)(…/TypoarWrokPath/images/1615268554539.png)]
1.SortBean代码
public class SortBean implements WritableComparable<SortBean> {
//创建变量并且set get and toString
private String word;
private int num;
@Override
public String toString() {
return word + '\t' + num;
}
public String getWord() {
return word;
}
public void setWord(String word) {
this.word = word;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
//实现WritableComparablede的方法
//实行比较器,指定排序规则
public int compareTo(SortBean o) {
//意思就是告诉比较器 在什么时候大于零什么时候小于零 什么时候等于零 比较器会自动帮你排序好
//先对第一列进行排序 对英文字母的asci码进行比较
int i = this.word.compareTo(o.word);
if (i == 0) { //如果第一列相同就对第二列进行升序排序 降序就用后面的减去前面的
return this.num - o.num;
}
return i;
}
//实现序列化
public void write(DataOutput dataOutput) throws IOException {
dataOutput.writeUTF(word);
dataOutput.writeInt(num);
}
//反序列化
public void readFields(DataInput dataInput) throws IOException {
this.word = dataInput.readUTF(); //读取字符串
this.num = dataInput.readInt();//读取数字
}
}
2.SortMapper代码
public class SortMapper extends Mapper<LongWritable,Text,SortBean,NullWritable> {
//map方法就是将k1 v1 转为 k2 v2
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
//将行文本数据(value)拆分,并将数据封装到SortBean中(k2)
String[] split = value.toString().split("\t");
System.out.println("split[0]-->"+split[0]);
System.out.println("split[1])-->"+split[1]);
SortBean sortBean = new SortBean();
sortBean.setWord(split[0]);
sortBean.setNum(Integer.parseInt(split[1]));
//将k2 和v2 保存到上下文中
context.write(sortBean,NullWritable.get());
}
}
3.SortReduce 代码
public class SortReduce extends Reducer<SortBean, NullWritable,SortBean,NullWritable> {
@Override
protected void reduce(SortBean key, Iterable<NullWritable> values, Context context) throws IOException, InterruptedException {
context.write(key,NullWritable.get());
}
}
4.JobMain代码
public class JobMain extends Configured implements Tool {
//启动job任务
public static void main(String[] args) throws Exception {
int run = ToolRunner.run(new Configuration(), new JobMain(), args);
System.out.println("任务完成");
System.exit(run);
}
public int run(String[] strings) throws Exception {
//创建job对象
Job job = Job.getInstance(super.getConf(), "mapreduce_sort");
//配置job任务
//设置输入类和输入的路径
job.setInputFormatClass(TextInputFormat.class);
TextInputFormat.addInputPath(job, new Path("hdfs://singlenode:8020/sort"));
//TextInputFormat.addInputPath(job, new Path("file:///D:\\sort.txt"));
//设置mapper类和数据类型
job.setMapperClass(SortMapper.class);
job.setMapOutputKeyClass(SortBean.class);
job.setMapOutputValueClass(NullWritable.class);
//3.4.5.6
//设置reduce嘞和数据类型
job.setReducerClass(SortReduce.class);
job.setOutputKeyClass(SortBean.class);
job.setOutputValueClass(NullWritable.class);
//设置输出类
job.setOutputFormatClass(TextOutputFormat.class);
TextOutputFormat.setOutputPath(job, new Path("hdfs://singlenode:8020/out/sort_out"));
//TextOutputFormat.setOutputPath(job, new Path("file:///D:\\sort123"));
//等待任务
boolean b = job.waitForCompletion(true);
return b ? 0 : 1;
}
}
37.MapReduce规约
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9EDxy7nS-1623596660319)(…/TypoarWrokPath/images/1615295152945.png)]
1.实现步骤 创建一个MyCombiner类,实现Reduce 和之前的Reduce一样就好
//自定义的Combiner
public class MyCombiner extends Reducer<Text, LongWritable,Text,LongWritable> {
@Override
protected void reduce(Text key, Iterable<LongWritable> values, Context context) throws IOException, InterruptedException {
long count = 0;
for (LongWritable value : values) {
count += value.get();
}
//2.将k3 v3写入上下文中
context.write(key, new LongWritable(count));
}
}
2.在主程序中设置规约
// .5(规约).设置规约
job.setCombinerClass(MyCombiner.class);
没有Combiner的运行结果图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hqKAu1UM-1623596660319)(…/TypoarWrokPath/images/1615301209022.png)]
运行结果图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mnMBg5gS-1623596660320)(…/TypoarWrokPath/images/1615301156001.png)]
38.MapReduce的机制—MapTesk和ReduceTast的机制
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MSQ2jurN-1623596660322)(…/TypoarWrokPath/images/1-MapReduce工作机制-全流程.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t9iaiFGN-1623596660324)(…/TypoarWrokPath/images/1615374731519.png)]
39.Reduce操作JOIN的案列
1.Mapper代码
/*
* k1 LongWrtable
* v2 Text
*
* k2 Text 商品的id
* v2 Text
* */
public class JoinMapper extends Mapper<LongWritable, Text,Text,Text> {
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
//判断文件来自那个文件
FileSplit fileSplit = (FileSplit) context.getInputSplit(); //获取文件的切片
String name = fileSplit.getPath().getName(); //获取文件的名字
if(name.equals("product.txt")){
//来自商品表
//将k1 and v1 转为 k2 and v2
String[] split = value.toString().split(",");
String productid=split[0];
context.write(new Text(productid),value);
}else{
//来自订单表
//将k1 and v1 转为 k2 and v2
String[] split = value.toString().split(",");
String orderpid = split[2];
context.write(new Text(orderpid),value);
}
}
}
2.Reduce的代码
public class JoinReduce extends Reducer<Text,Text,Text,Text> {
@Override
protected void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
//遍历集合获取v3
String first="";
String secoud="";
for (Text value : values) {
if(value.toString().startsWith("p")){ //判断文件的开头是商品表还是订单表
first=value.toString(); //商品表就加入first
}else{
secoud+=value.toString(); //不是就缀加到secoud后面
}
}
//将k3 and v3 写入上下文
context.write(key,new Text(first+"\t"+secoud));
}
}
3.Job代码
public class JoinJob extends Configured implements Tool {
public static void main(String[] args) throws Exception {
int run = ToolRunner.run(new Configuration(), new JoinJob(), args);
System.out.println("任务完成");
System.exit(run);
}
@Override
public int run(String[] strings) throws Exception {
Job job = Job.getInstance(super.getConf(), "Join_Test");
job.setJarByClass(JoinJob.class);
TextInputFormat.addInputPath(job, new Path("file:///D:/join"));
// TextInputFormat.addInputPath(job, new Path("hdfs://node01:8020/join"));
job.setMapperClass(JoinMapper.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(Text.class);
job.setReducerClass(JoinReduce.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(Text.class);
TextOutputFormat.setOutputPath(job, new Path("file:///D:/joinout"));
//TextOutputFormat.setOutputPath(job, new Path("hdfs://node01:8020/joinout"));
boolean b = job.waitForCompletion(true);
return b ? 0 : 1;
}
}
40.Mapper阶段操作JOIN
1.MapperJoinJob代码
package lhh.com.MapperJoin;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;
import java.net.URI;
/**
* @program: lhh
* @description:
* @author: 华仔
* @create: 2021-03-10 22:54
*/
public class MapperJoinJob extends Configured implements Tool {
public static void main(String[] args) throws Exception {
int run = ToolRunner.run(new Configuration(), new MapperJoinJob(), args);
System.out.println("任务完成");
System.exit(run);
}
@Override
public int run(String[] strings) throws Exception {
//获取job对象
Job job = Job.getInstance(super.getConf(), "MapperJoin");
//配置job对象
//将小表放在分布式的缓存中,
job.addCacheFile(new URI("hdfs://node01:8020/join/product.txt"));
job.setInputFormatClass(TextInputFormat.class);
TextInputFormat.addInputPath(job, new Path("file:///D:/join/mapper"));
job.setMapperClass(MapperMapper.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(Text.class);
job.setOutputFormatClass(TextOutputFormat.class);
TextOutputFormat.setOutputPath(job, new Path("file:///D:/mapperjoinout"));
boolean b = job.waitForCompletion(true);
return b ? 0 : 1;
}
}
2.Mappermapeer代码
package lhh.com.MapperJoin;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URI;
import java.util.HashMap;
/**
* @program: lhh
* @description:
* @author: 华仔
* @create: 2021-03-10 22:54
*/
public class MapperMapper extends Mapper<LongWritable, Text,Text,Text> {
//第一间事情:将分布式的小表数据读取到本地的map集合(只需要做一次)
//用于保存读取出来的数据
private HashMap<String, String> hashMap = new HashMap<>();
@Override
protected void setup(Context context) throws IOException, InterruptedException {
//1.获分布式文件缓存的所有列表
URI[] cacheFiles = context.getCacheFiles();
//2.获取指定的分布式缓存文件的文件系统(FileSystem)
// 因为存在分布式缓存的文件是以列表存的所以 cacheFiles[0]是指获取第一个文件
FileSystem fileSystem = FileSystem.get(cacheFiles[0], context.getConfiguration());
//3.获取文件内容,并将数据存入map集合
FSDataInputStream open = fileSystem.open(new Path(cacheFiles[0]));
//4读取文件内容,并且存入Map集合中
//4.1将字节输入流转为字符缓冲流
//new InputStreamReader(open) 使用 InputStreamReader 将字节流变成字符流
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(open));
//4.2读取小文件内容,一行为单位,并将读取的数据存入Map集合
String line =null;
while ((line =bufferedReader.readLine())!=null){
String[] split = line.split(",");
hashMap.put(split[0],line);
}
//5.关闭流,释放资源
bufferedReader.close();
fileSystem.close();
}
//2第二件事情:对大表处理业务逻辑,而且要实现大表和小表的join操作
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
String[] split = value.toString().split(",");
String productid=split[2];
String productFile = hashMap.get(productid);
String wenben = value.toString()+"\t"+productFile;
context.write(new Text(productid),new Text(wenben));
}
}
41.自定义InputFormat实现小文件合并
特点:决定数据的读取方式
1.自定义InputFormat的流程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eEoh8Czk-1623596660325)(…/TypoarWrokPath/images/1615476111800.png)]
2.代码
1.自定义的MyInputFormat代码
package lhh.com.MapreduceInputFormat;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.BytesWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.mapreduce.InputSplit;
import org.apache.hadoop.mapreduce.JobContext;
import org.apache.hadoop.mapreduce.RecordReader;
import org.apache.hadoop.mapreduce.TaskAttemptContext;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import java.io.IOException;
/**
* @program: lhh
* @description:
* @author: 华仔
* @create: 2021-03-11 23:24
*/
//泛型使用自己需要的类型
public class MyInputFormat extends FileInputFormat<NullWritable, BytesWritable> {
@Override
public RecordReader<NullWritable, BytesWritable> createRecordReader(InputSplit inputSplit, TaskAttemptContext taskAttemptContext) throws IOException, InterruptedException {
//创建自定RecordReader对象
MyRecordReader myRecordReader = new MyRecordReader();
//将inputSplit and taskAttemptContext 传给自定义的MyRecordreader
myRecordReader.initialize(inputSplit,taskAttemptContext);
return myRecordReader;
}
@Override //设置文件是否可以切片
protected boolean isSplitable(JobContext context, Path filename) {
// false 不可以
//true 可以
return false;
}
}
2.自定义的MyRecordReader 代码
package lhh.com.MapreduceInputFormat;
import org.apache.commons.io.IOUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.io.BytesWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.mapreduce.InputSplit;
import org.apache.hadoop.mapreduce.RecordReader;
import org.apache.hadoop.mapreduce.TaskAttemptContext;
import org.apache.hadoop.mapreduce.lib.input.FileSplit;
import java.io.IOException;
/**
* @program: lhh
* @description:
* @author: 华仔
* @create: 2021-03-11 23:36
*/
public class MyRecordReader extends RecordReader<NullWritable, BytesWritable> {
private Configuration configuration = null;
private FileSplit fileSplit = null;
private boolean processd=false;
private BytesWritable bytesWritable = new BytesWritable();
private FileSystem fileSystem=null;
private FSDataInputStream inputStream=null;
//进行初始化工作
@Override//inputSplit 系统文件的切片
public void initialize(InputSplit inputSplit, TaskAttemptContext taskAttemptContext) throws IOException, InterruptedException {
//获取文件的切片
fileSplit = (FileSplit) inputSplit;
//获取configuration对象
configuration = taskAttemptContext.getConfiguration();
}
//用于获取k1 v2 (通过读取元数据转成k1 v1)
@Override
public boolean nextKeyValue() throws IOException, InterruptedException {
if(!processd){ //如果processd是fasle,(取反)那么就进来进行读取文件
//1.获取源文件的字节输入流
//1.1获取源文件的文件系统(FileSystem)
fileSystem = FileSystem.get(configuration);
//1.2通过FileSystem获取文件字节输入流 ileSplit.getPath()拿到源文件的路径
inputStream = fileSystem.open(fileSplit.getPath());
//2.读取源文件数据到普通的字节数组中(byte[]) fileSplit.getLength() 获取整个文件的大小
byte[] bytes = new byte[(int) fileSplit.getLength()];
//参数 1输入流 2.存到byte数组中 3.第一次从哪里存 4.一次性存多大
IOUtils.readFully(inputStream,bytes,0,(int) fileSplit.getLength());
//3.将普通字节数组封装到BytesWritable,得到v1
bytesWritable.set(bytes,0,(int)fileSplit.getLength());
processd =true; //读取完成之后修改为true
return true;
}
return false;
}
//返回k1
@Override
public NullWritable getCurrentKey() throws IOException, InterruptedException {
return NullWritable.get();
}
//返回v1
@Override
public BytesWritable getCurrentValue() throws IOException, InterruptedException {
return bytesWritable;
}
//获取文件的读取进度
@Override
public float getProgress() throws IOException, InterruptedException {
return 0;
}
//进行文件的释放
@Override
public void close() throws IOException {
inputStream.close();
fileSystem.close();
}
}
3.SequenceFileMapper普通的map类
package lhh.com.MapreduceInputFormat;
import org.apache.hadoop.io.BytesWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.lib.input.FileSplit;
import java.io.IOException;
/**
* @program: lhh
* @description:
* @author: 华仔
* @create: 2021-03-12 00:29
*/
public class SequenceFileMapper extends Mapper<NullWritable, BytesWritable, Text, BytesWritable> {
@Override
protected void map(NullWritable key, BytesWritable value, Context context) throws IOException, InterruptedException {
//获取文件的名字作为k2
FileSplit fileSplit = (FileSplit) context.getInputSplit();
//获取文件的名字
String name = fileSplit.getPath().getName();
//将k2 and v2 写入上下文中
context.write(new Text(name), value);
}
}
4.JobMain代码
package lhh.com.MapreduceInputFormat;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.BytesWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.output.SequenceFileOutputFormat;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;
/**
* @program: lhh
* @description:
* @author: 华仔
* @create: 2021-03-12 00:39
*/
public class JobMain extends Configured implements Tool {
public static void main(String[] args) throws Exception {
int run = ToolRunner.run(new Configuration(), new JobMain(), args);
System.out.println("任务完成");
System.exit(run);
}
@Override
public int run(String[] strings) throws Exception {
Job job = Job.getInstance(super.getConf(), "MapperInputForMat");
//设置输入类和输入路径
job.setInputFormatClass(MyInputFormat.class);
MyInputFormat.addInputPath(job, new Path("file:///D:/input/myinputformat"));
//设置mapper类和路径
job.setMapperClass(SequenceFileMapper.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(BytesWritable.class);
//不需要设置reduce类但是需要设置输出类型
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(BytesWritable.class);
job.setOutputFormatClass(SequenceFileOutputFormat.class);
SequenceFileOutputFormat.setOutputPath(job, new Path("file:///D:/out/SequenceFileOutputFormatout"));
boolean b = job.waitForCompletion(true);
return b ? 0 : 1;
}
}
42自定义OutPutFormat
特点:决定数据的写入方式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KGXpxXGe-1623596660326)(…/TypoarWrokPath/images/1615527327892.png)]
1.MyOutputFormat代码
package lhh.com.MapReduceOutPutFormat;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.RecordWriter;
import org.apache.hadoop.mapreduce.TaskAttemptContext;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import java.io.IOException;
/**
* @program: lhh
* @description:
* @author: 华仔
* @create: 2021-03-12 13:39
*/
public class MyOutputFormat extends FileOutputFormat<Text, NullWritable> {
@Override
public RecordWriter<Text, NullWritable> getRecordWriter(TaskAttemptContext taskAttemptContext) throws IOException, InterruptedException {
//获取目标文件的输出流
FileSystem fileSystem = FileSystem.get(taskAttemptContext.getConfiguration());
//这个路径是设置把运行出来的结果文件存到哪里
FSDataOutputStream goodDataOutputStream = fileSystem.create(new Path("file:///D:/out/haopin"));
FSDataOutputStream chapinDataOutputStream = fileSystem.create(new Path("file:///D:/out/chapin"));
//将输出流转给自定义的myrecordwriter
MyRecordWriter myRecordWriter = new MyRecordWriter(goodDataOutputStream,chapinDataOutputStream);
return myRecordWriter;
}
}
2.MyRecordWriter代码
package lhh.com.MapReduceOutPutFormat;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.RecordWriter;
import org.apache.hadoop.mapreduce.TaskAttemptContext;
import java.io.IOException;
/**
* @program: lhh
* @description:
* @author: 华仔
* @create: 2021-03-12 13:40
*/
public class MyRecordWriter extends RecordWriter<Text, NullWritable> {
private FSDataOutputStream goodDataOutputStreamt;
private FSDataOutputStream chapinDataOutputStream;
public MyRecordWriter(FSDataOutputStream goodDataOutputStreamt, FSDataOutputStream chapinDataOutputStream) {
this.goodDataOutputStreamt = goodDataOutputStreamt;
this.chapinDataOutputStream = chapinDataOutputStream;
}
public MyRecordWriter() {
}
/**
* @param text 行文本值
* @param nullWritable
* @throws IOException
* @throws InterruptedException
*/
@Override
public void write(Text text, NullWritable nullWritable) throws IOException, InterruptedException {
//1.从行文本数据中获取第九个字段
String[] split = text.toString().split("\t");
String numstr = split[9];
//2.根据字段的值,判断评论去的类型,然后将对应的数据写入不同的文件夹中
if (Integer.parseInt(numstr) <= 1) {
//好评或者中评
//写入数据
goodDataOutputStreamt.write(text.toString().getBytes());
//写入换行符
goodDataOutputStreamt.write("\r\n".getBytes()); //\r\n表示换行符
} else {
//差评
//写入数据
chapinDataOutputStream.write(text.toString().getBytes());
//写入换行符
goodDataOutputStreamt.write("\r\n".getBytes()); //\r\n表示换行符
}
}
@Override //释放资源
public void close(TaskAttemptContext taskAttemptContext) throws IOException, InterruptedException {
IOUtils.closeStream(goodDataOutputStreamt);
IOUtils.closeStream(chapinDataOutputStream);
}
}
3.OutputFormatMapper代码
package lhh.com.MapReduceOutPutFormat;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import java.io.IOException;
/**
* @program: lhh
* @description:
* @author: 华仔
* @create: 2021-03-12 14:08
*/
public class OutputFormatMapper extends Mapper<LongWritable, Text,Text, NullWritable> {
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
context.write(value,NullWritable.get());
}
}
4.OutputFormatJob代码
package lhh.com.MapReduceOutPutFormat;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;
/**
* @program: lhh
* @description:
* @author: 华仔
* @create: 2021-03-12 12:18
*/
public class OutputFormatJob extends Configured implements Tool {
public static void main(String[] args) throws Exception {
int run = ToolRunner.run(new Configuration(), new OutputFormatJob(), args);
System.exit(run);
}
@Override
public int run(String[] strings) throws Exception {
Job job = Job.getInstance(super.getConf(), "outputfoemat_test");
job.setInputFormatClass(TextInputFormat.class);
TextInputFormat.addInputPath(job, new Path("file:///D:/input/outputformat"));
job.setMapperClass(OutputFormatMapper.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(NullWritable.class);
job.setOutputFormatClass(MyOutputFormat.class);
TextOutputFormat.setOutputPath(job, new Path("file:///D:/out/outputformatout"));
boolean b = job.waitForCompletion(true);
return b ? 0 : 1;
}
}
43,自定义分组
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7i94le43-1623596660327)(…/TypoarWrokPath/images/1615559367913.png)]
1需求
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kJNAv1BF-1623596660327)(…/TypoarWrokPath/images/1615565503729.png)]
1.OrderBean代码
package lhh.com.MapGroup;
import org.apache.hadoop.io.WritableComparable;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
/**
* @program: lhh
* @description:
* @author: 华仔
* @create: 2021-03-12 23:06
*/
public class OrderBean implements WritableComparable<OrderBean> {
private String orderId;
private Double price;
@Override
public String toString() {
return orderId + "\t" + price;
}
public String getOrderId() {
return orderId;
}
public void setOrderId(String orderId) {
this.orderId = orderId;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
@Override
public int compareTo(OrderBean o) {
//先比较订单id,如果一致就根据金额排序(降序)
int i = this.orderId.compareTo(o.getOrderId());
if(i==0){
//乘-1 变成降序
i = this.price.compareTo(o.getPrice())*-1 ;
}
return i;
}
@Override
public void write(DataOutput dataOutput) throws IOException {
dataOutput.writeUTF(this.orderId);
dataOutput.writeDouble(this.price);
}
@Override
public void readFields(DataInput dataInput) throws IOException {
this.orderId = dataInput.readUTF();
this.price = dataInput.readDouble();
}
}
2.OrderMapper代码
package lhh.com.MapGroup;
import org.apache.hadoop.io.WritableComparable;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
/**
* @program: lhh
* @description:
* @author: 华仔
* @create: 2021-03-12 23:06
*/
public class OrderBean implements WritableComparable<OrderBean> {
private String orderId;
private Double price;
@Override
public String toString() {
return orderId + "\t" + price;
}
public String getOrderId() {
return orderId;
}
public void setOrderId(String orderId) {
this.orderId = orderId;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
@Override
public int compareTo(OrderBean o) {
//先比较订单id,如果一致就根据金额排序(降序)
int i = this.orderId.compareTo(o.getOrderId());
if(i==0){
//乘-1 变成降序
i = this.price.compareTo(o.getPrice())*-1 ;
}
return i;
}
@Override
public void write(DataOutput dataOutput) throws IOException {
dataOutput.writeUTF(this.orderId);
dataOutput.writeDouble(this.price);
}
@Override
public void readFields(DataInput dataInput) throws IOException {
this.orderId = dataInput.readUTF();
this.price = dataInput.readDouble();
}
}
3.OrderPartition代码
package lhh.com.MapGroup;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Partitioner;
/**
* @program: lhh
* @description:
* @author: 华仔
* @create: 2021-03-12 23:21
*/
//这里的类型就是k2 v2 的类型
public class OrderPartition extends Partitioner<OrderBean, Text> {
//分区规则根据订单的id实现分区
/**
* @param orderBean k2
* @param text v2
* @param i reducetask 的个数
* @return 返回分区的编号
*/
@Override
public int getPartition(OrderBean orderBean, Text text, int i) {
return (orderBean.getOrderId().hashCode() & 2147483647) % i;
}
}
4.OrderGroup代码
package lhh.com.MapGroup;
import org.apache.hadoop.io.WritableComparable;
import org.apache.hadoop.io.WritableComparator;
/**
* @program: lhh
* @description:
* @author: 华仔
* @create: 2021-03-12 23:36
*/
//WritableComparator
public class OrderGroup extends WritableComparator {
//调用父类的有参构造
public OrderGroup() {
super(OrderBean.class, true);
}
@Override //指定分组的规则(重写方法)
public int compare(WritableComparable a, WritableComparable b) {
//3.1对形参强转
OrderBean orderBean01 = (OrderBean) a;
OrderBean orderBean02 = (OrderBean) b;
//如果id相同就是同一组
return orderBean01.getOrderId().compareTo(orderBean02.getOrderId());
}
}
5.OrderReduce代码
package lhh.com.MapGroup;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
import java.io.IOException;
/**
* @program: lhh
* @description:
* @author: 华仔
* @create: 2021-03-12 23:21
*/
public class OrderReduce extends Reducer<OrderBean, Text, Text, NullWritable> {
@Override
protected void reduce(OrderBean key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
int i = 0;
for (Text value : values) {
context.write(value, NullWritable.get());
i++;
if (i >= 2) {
break;
}
}
}
}
6.OrderJob代码
package lhh.com.MapGroup;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;
/**
* @program: lhh
* @description:
* @author: 华仔
* @create: 2021-03-12 23:57
*/
public class OrderJob extends Configured implements Tool {
//启动job任务
public static void main(String[] args) throws Exception {
int run = ToolRunner.run(new Configuration(), new OrderJob(), args);
System.out.println("任务完成");
System.exit(run);
}
@Override
public int run(String[] strings) throws Exception {
//创建job对象
Job job = Job.getInstance(super.getConf(), "OrderTest");
//配置job任务
//设置输入类和输入的路径
job.setInputFormatClass(TextInputFormat.class);
//TextInputFormat.addInputPath(job, new Path("hdfs://singlenode:8020/sort"));
TextInputFormat.addInputPath(job, new Path("file:///D:/input/order"));
//设置mapper类和数据类型
job.setMapperClass(OrderMapper.class);
job.setMapOutputKeyClass(OrderBean.class);
job.setMapOutputValueClass(Text.class);
//3.4.5.6
job.setPartitionerClass(OrderPartition.class);
//设置分组
job.setGroupingComparatorClass(OrderGroup.class);
//设置reduce嘞和数据类型
job.setReducerClass(OrderReduce.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(NullWritable.class);
//设置输出类
job.setOutputFormatClass(TextOutputFormat.class);
//TextOutputFormat.setOutputPath(job, new Path("hdfs://singlenode:8020/out/sort_out"));
TextOutputFormat.setOutputPath(job, new Path("file:///D:/out/orderout"));
//等待任务
boolean b = job.waitForCompletion(true);
return b ? 0 : 1;
}
}
44.yarn资源调度
yarn****的介绍:****
yarn是hadoop集群当中的资源管理系统模块,从hadoop2.0开始引入yarn模块,yarn可为各类计算框架提供资源的管理和调度,主要用于管理集群当中的资源(主要是服务器的各种硬件资
源,包括CPU,内存,磁盘,网络IO等)以及调度运行在yarn上面的各种任务。
yarn核心出发点是为了分离资源管理与作业监控,实现分离的做法是拥有一个全局的资源管理(ResourceManager,RM),以及每个应用程序对应一个的应用管理器
(ApplicationMaster,AM)
总结一句话就是说:yarn主要就是为了调度资源,管理任务等其调度分为两个层级来说:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JGf5t6ql-1623596660329)(…/TypoarWrokPath/images/wps1.png)]一级调度管理:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nZfT757l-1623596660330)(…/TypoarWrokPath/images/wps2.png)]计算资源管理(CPU,内存,网络IO,磁盘) 二级调度管理:
任务内部的计算模型管理 (AppMaster的任务精细化管理)
yarn官方文档
yarn****的官网文档说明:****
http://hadoop.apache.org/docs/r2.7.5/hadoop-yarn/hadoop-yarn-site/YARN.html y
arn****集群的监控管理界面:****
http://node01:8088/cluster
jobHistoryServer *查 看 界 面 :* http://node01:19888/jobhistory
yarn的主要组件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UgcfBTDb-1623596660330)(…/TypoarWrokPath/images/wps3.png)],主要由ResourceManager、NodeManager、
ApplicationMaster和Container等几个组件构成。
ResourceManager(RM)
负责处理客户端请求,对各NM上的资源进行统一管理和调度。给ApplicationMaster分配空 闲的Container 运行并监控其运行状态。主要由两个组件构成:调度器和应用程序管理器:
\1. ****调度器****(Scheduler):调度器根据容量、队列等限制条件,将系统中的资源分配给各个正在运行的应用程序。调度器仅根据各个应用程序的资源需求进行资源分配,而资源分配单位是Container。Shceduler不负责监控或者跟踪应用程序的状态。总之,调度器根据应用程序的资源要求,以及集群机器的资源情况,为应用程序分配封装在Container中的资源。
\2. ****应用程序管理器****(Applications Manager):应用程序管理器负责管理整个系统中所有应用程序,包括应用程序提交、与调度器协商资源以启动ApplicationMaster 、监控ApplicationMaster运行状态并在失败时重新启动等,跟踪分给的Container的进度、状态也是其职责。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bbWlL9vh-1623596660331)(…/TypoarWrokPath/images/wps4.png)]NodeManager (NM)
NodeManager 是每个节点上的资源和任务管理器。它会定时地向ResourceManager汇报本节点上的资源使用情况和各个Container的运行状态;同时会接收并处理来自ApplicationMaster 的Container 启动/停止等请求。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Dsz0LwHf-1623596660333)(…/TypoarWrokPath/images/wps5.png)]ApplicationMaster (AM):
用户提交的应用程序均包含一个ApplicationMaster ,负责应用的监控,跟踪应用执行状态,重启失败任务等。ApplicationMaster是应用框架,它负责向ResourceManager协调资源,并且与NodeManager协同工作完成Task的执行和监控。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K95DN5Aj-1623596660334)(…/TypoarWrokPath/images/wps6.png)]Container:
Container是YARN中的资源抽象,它封装了某个节点上的多维度资源,如内存、CPU、磁盘、网络等,当ApplicationMaster向ResourceManager申请资源时,ResourceManager为ApplicationMaster 返回的资源便是用Container 表示的。
yarn的架构和工作流程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HBEsh32X-1623596660335)(…/TypoarWrokPath/images/4-yarn的工作流程.jpg)]
yarn的调度器
第一种调度器 FIFO Scheduler(队列调度)
把任务按提交的顺序排成一个队列,这是一个先进先出队列,在进行资源分配的时候,先给队列中最头上的任务进行分配资源,待最头上任务需求满足后再给下一个分配,以此类推。
FIFO Scheduler是最简单也是最容易理解的调度器,也不需要任何配置,但它并不适用于共享集群。大的任务可能会占用所有集群资源,这就导致其它任务被阻塞。
第二种调度器 Capacity Scheduler(容量调度器,默认使用的调度器)
Capacity 调度器允许多个组织共享整个集群,每个组织可以获得集群的一部分计算能力。通过为每个组织分配专门的队列,然后再为每个队列分配一定的集群资源,这样整个集群就可以通过设置多个队列的方式给多个组织提供服务了。除此之外,队列内部又可以垂直划分, 这样一个组织内部的多个成员就可以共享这个队列资源了,在一个队列内部,资源的调度是采用的是先进先出(FIFO)策略。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tfIVB82U-1623596660336)(…/TypoarWrokPath/images/1615601876283.png)]
第三种调度器 Fari Scheduler(公平调度器,CDH版本的默认调度器)
Fair调度器的设计目标是为所有的应用分配公平的资源(对公平的定义可以通过参数来设置)。公平调度在也可以在多个队列间工作。举个例子,假设有两个用户A和B,他们分别拥有一个队列。当A启动一个job而B没有任务时,A会获得全部集群资源;当B启动一个job后,A 的job会继续运行,不过一会儿之后两个任务会各自获得一半的集群资源。如果此时B再启动第二个job并且其它job还在运行,则它将会和B的第一个job共享B这个队列的资源,也就是B的两个job会用于四分之一的集群资源,而A的job仍然用于集群一半的资源,结果就是资源最终在两个用户之间平等的共享
1. *关于*yarn*常用参数设置*
*设置*container*分配最小内存*
yarn.scheduler.minimum-allocation-mb 1024 给应用程序container分配的最小内存
*设置*container*分配最大内存*
yarn.scheduler.maximum-allocation-mb 8192 给应用程序container分配的最大内存
*设置每个*container*的最小虚拟内核个数*
yarn.scheduler.minimum-allocation-vcores 1 每个container默认给分配的最小的虚拟内核个数
*设置每个*container*的最大虚拟内核个数*
度。给ApplicationMaster分配空 闲的Container 运行并监控其运行状态。主要由两个组件构成:调度器和应用程序管理器:
\1. ****调度器****(Scheduler):调度器根据容量、队列等限制条件,将系统中的资源分配给各个正在运行的应用程序。调度器仅根据各个应用程序的资源需求进行资源分配,而资源分配单位是Container。Shceduler不负责监控或者跟踪应用程序的状态。总之,调度器根据应用程序的资源要求,以及集群机器的资源情况,为应用程序分配封装在Container中的资源。
\2. ****应用程序管理器****(Applications Manager):应用程序管理器负责管理整个系统中所有应用程序,包括应用程序提交、与调度器协商资源以启动ApplicationMaster 、监控ApplicationMaster运行状态并在失败时重新启动等,跟踪分给的Container的进度、状态也是其职责。
[外链图片转存中…(img-bbWlL9vh-1623596660331)]NodeManager (NM)
NodeManager 是每个节点上的资源和任务管理器。它会定时地向ResourceManager汇报本节点上的资源使用情况和各个Container的运行状态;同时会接收并处理来自ApplicationMaster 的Container 启动/停止等请求。
[外链图片转存中…(img-Dsz0LwHf-1623596660333)]ApplicationMaster (AM):
用户提交的应用程序均包含一个ApplicationMaster ,负责应用的监控,跟踪应用执行状态,重启失败任务等。ApplicationMaster是应用框架,它负责向ResourceManager协调资源,并且与NodeManager协同工作完成Task的执行和监控。
[外链图片转存中…(img-K95DN5Aj-1623596660334)]Container:
Container是YARN中的资源抽象,它封装了某个节点上的多维度资源,如内存、CPU、磁盘、网络等,当ApplicationMaster向ResourceManager申请资源时,ResourceManager为ApplicationMaster 返回的资源便是用Container 表示的。
yarn的架构和工作流程
[外链图片转存中…(img-HBEsh32X-1623596660335)]
yarn的调度器
第一种调度器 FIFO Scheduler(队列调度)
把任务按提交的顺序排成一个队列,这是一个先进先出队列,在进行资源分配的时候,先给队列中最头上的任务进行分配资源,待最头上任务需求满足后再给下一个分配,以此类推。
FIFO Scheduler是最简单也是最容易理解的调度器,也不需要任何配置,但它并不适用于共享集群。大的任务可能会占用所有集群资源,这就导致其它任务被阻塞。
第二种调度器 Capacity Scheduler(容量调度器,默认使用的调度器)
Capacity 调度器允许多个组织共享整个集群,每个组织可以获得集群的一部分计算能力。通过为每个组织分配专门的队列,然后再为每个队列分配一定的集群资源,这样整个集群就可以通过设置多个队列的方式给多个组织提供服务了。除此之外,队列内部又可以垂直划分, 这样一个组织内部的多个成员就可以共享这个队列资源了,在一个队列内部,资源的调度是采用的是先进先出(FIFO)策略。
[外链图片转存中…(img-tfIVB82U-1623596660336)]
第三种调度器 Fari Scheduler(公平调度器,CDH版本的默认调度器)
Fair调度器的设计目标是为所有的应用分配公平的资源(对公平的定义可以通过参数来设置)。公平调度在也可以在多个队列间工作。举个例子,假设有两个用户A和B,他们分别拥有一个队列。当A启动一个job而B没有任务时,A会获得全部集群资源;当B启动一个job后,A 的job会继续运行,不过一会儿之后两个任务会各自获得一半的集群资源。如果此时B再启动第二个job并且其它job还在运行,则它将会和B的第一个job共享B这个队列的资源,也就是B的两个job会用于四分之一的集群资源,而A的job仍然用于集群一半的资源,结果就是资源最终在两个用户之间平等的共享
1. *关于*yarn*常用参数设置*
*设置*container*分配最小内存*
yarn.scheduler.minimum-allocation-mb 1024 给应用程序container分配的最小内存
*设置*container*分配最大内存*
yarn.scheduler.maximum-allocation-mb 8192 给应用程序container分配的最大内存
*设置每个*container*的最小虚拟内核个数*
yarn.scheduler.minimum-allocation-vcores 1 每个container默认给分配的最小的虚拟内核个数
*设置每个*container*的最大虚拟内核个数*
yarn.scheduler.maximum-allocation-vcores 32 每个container可以分配的最大的虚拟内核的个数