Hadoop-Mapreduce

本文详细介绍了Hadoop MapReduce的概念、设计理念、架构变迁(从1.x到2.x),并逐步解析了MapReduce的计算流程,包括数据切片、MapTask、ReduceTask的执行过程。此外,还分享了WordCount案例的Java实现和MapReduce的源码分析。最后,文章提供了天气信息处理、PageRank算法和TF-IDF权重计算等多个MapReduce应用案例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Hadoop-Mapreduce

1. 扑克牌问题

在这里插入图片描述

  • 假如你有2000副四大名著主题扑克牌。现在将他们全部混合在一起,然后从中随机抽出一部分丢
    掉,现在要求你统计出每种名著分别有多少张?
    • 统计扑克牌人数不限(20人)

2. MapReduce设计理念

  • map–>映射(key value)
  • reduce–>归纳
  • mapreduce必须构建在hdfs之上一种大数据离线计算框架
    • 在线:实时数据处理
    • 离线:数据处理时效性没有在线那么强,但是相对也需要很快得到结果
  • mapreduce不会马上得到结果,他会有一定的延时
    • 如果数据量小,使用mapreduce反而不合适
    • 杀鸡用牛刀
  • 原始数据–>map(Key,Value)–>Reduce
  • 分布式计算
    • 将大的数据切分成多个小数据,交给更多的节点参与运算
  • 计算向数据靠拢
    • 将计算传递给有数据的节点上进行工作

3. MapReduce架构

3.1. MapReduce1.x

在这里插入图片描述

  • client
    • 客户端发送mr任务到集群
    • 客户端的种类有很多种
      • hadoop jar wordcount.jar
  • JobTracker
    • 接受客户端的mr任务
      • 选择一个资源丰富的,执行对应的任务
      • 并且给这个任务分配资源
    • 与TaskTracker保持心跳,接受汇报信息
  • TaskTracker
    • 保持心跳,汇报资源
      • 当前机器内存,当前机器任务数
    • 当分配资源之后,开始在本机分配对应的资源给Task
    • 并且实时监控任务的执行,并汇报
  • Slot(槽)
    • 属于JobTracker分配的资源
    • 计算能力,IO能力…
    • 不管任务大小,资源是恒定的,不灵活但是好管理
  • Task(MapTask–ReduceTask)
    • 开始按照MR的流程执行业务
    • 当任务完成时,JobTracker告诉TaskTracker回收资源

在这里插入图片描述

  • 缺点:
    • 单点故障
    • 内存扩展
    • 业务瓶颈
    • 只能执行MR的操作
      • 如果其他框架需要运行在Hadoop上,需要独立开发自己的资源调度框架

3.2. MapReduce2.x

在这里插入图片描述
在这里插入图片描述

  • 2.x开始使用Yarn(Yet Another Resource Negotiator,另一种资源协调者)统一管理资源
  • 以后其他的计算框架可以直接访问yarn获取当前集群的空闲节点
  • client
    • 客户端发送mr任务到集群
    • 客户端的种类有很多种
      • hadoop jar wordcount.jar
  • ResourceManager
    • 资源协调框架的管理者
    • 分为主节点和备用节点(防止单点故障)
      • 主备的切换基于Zookeeper进行管理
    • 时刻与NodeManager保持心跳,接受NodeManager的汇报
      • NodeManager汇报当前节点的资源情况
    • 当有外部框架要使用资源的时候直接访问ResourceManager即可
    • 如果有MR任务,先去ResourceManager申请资源,ResourceManager根据汇报相对灵活分配资源
      • 资源在NodeManager1,NodeManager1要负责开辟资源
  • NodeManager
    • Yet Another Resource Negotiator(另一种资源协调者)
    • 资源协调框架的执行者
    • 每一个DataNode上默认有一个NodeManager
    • NodeManager汇报自己的信息到ResourceManager
  • Container
    • 2.x资源的代名词
    • Container动态分配的
  • ApplicationMaster
    • 我们本次JOB任务的主导者
    • 负责调度本次被分配的资源Container
    • 当所有的节点任务全部完成,application告诉ResourceManager请求杀死当前ApplicationMaster线程
    • 本次任务所有的资源都会被释放
  • Task(MapTask–ReduceTask)
    • 开始按照MR的流程执行业务
    • 当任务完成时,ApplicationMaster接收到当前节点的回馈
      在这里插入图片描述

4. Hadoop搭建yarn环境

NameNode01 NameNode02 DateNode ZKFC ZooKeeper JournalNode ResourceManager NodeManager
Node01 * * * * * * *
Node02 * * * * * *
Node03 * * * * *
yarn环境搭建基于前面HA环境

4.1. 切换工作目录

  • [root@node01 ~]# cd /opt/bdp/hadoop-3.1.2/etc/hadoop/

4.2. 修改集群环境

  • [root@node01 hadoop]# vim hadoop-env.sh
##继续添加用户信息
export JAVA_HOME=/usr/java/jdk1.8.0_231-amd64
export HDFS_NAMENODE_USER=root
export HDFS_DATANODE_USER=root
export HDFS_ZKFC_USER=root
export HDFS_JOURNALNODE_USER=root
export YARN_RESOURCEMANAGER_USER=root
export YARN_NODEMANAGER_USER=root

4.3. 修改配置文件

  • [root@node01 hadoop]# vi mapred-site.xml
<!-- 指定mr框架为yarn方式 -->
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
<!-- 指定mapreduce jobhistory地址 -->
<property>
<name>mapreduce.jobhistory.address</name>
<value>node01:10020</value>
</property>
<!-- 任务历史服务器的web地址 -->
<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>node01:19888</value>
</property>
<!-- 配置运行过的日志存放在hdfs上的存放路径 -->
<property>
<name>mapreduce.jobhistory.done-dir</name>
<value>/history/done</value>
</property>
<!-- 配置正在运行中的日志在hdfs上的存放路径 -->
<property>
<name>mapreudce.jobhistory.intermediate.done-dir</name>
<value>/history/done/done_intermediate</value>
</property>
<property>
<name>mapreduce.application.classpath</name>
<value>
/opt/bdp/hadoop-3.1.2/etc/hadoop,
/opt/bdp/hadoop-3.1.2/share/hadoop/common/*,
/opt/bdp/hadoop-3.1.2/share/hadoop/common/lib/*,
/opt/bdp/hadoop-3.1.2/share/hadoop/hdfs/*,
/opt/bdp/hadoop-3.1.2/share/hadoop/hdfs/lib/*,
/opt/bdp/hadoop-3.1.2/share/hadoop/mapreduce/*,
/opt/bdp/hadoop-3.1.2/share/hadoop/mapreduce/lib/*,
/opt/bdp/hadoop-3.1.2/share/hadoop/yarn/*,
/opt/bdp/hadoop-3.1.2/share/hadoop/yarn/lib/*
</value>
</property>
  • [root@node01 hadoop]# vi yarn-site.xml
<!-- 开启RM高可用 -->
<property>
<name>yarn.resourcemanager.ha.enabled</name>
<value>true</value>
</property>
<!-- 指定RM的cluster id -->
<property>
<name>yarn.resourcemanager.cluster-id</name>
<value>yarn-bdp</value>
</property>
<!-- 指定RM的名字 -->
<property>
<name>yarn.resourcemanager.ha.rm-ids</name>
<value>rm1,rm2</value>
</property>
<!-- 分别指定RM的地址 -->
<property>
<name>yarn.resourcemanager.hostname.rm1</name>
<value>node01</value>
</property>
<property>
<name>yarn.resourcemanager.hostname.rm2</name>
<value>node03</value>
</property>
<property>
<name>yarn.resourcemanager.webapp.address.rm1</name>
<value>node01:8088</value>
</property>
<property>
<name>yarn.resourcemanager.webapp.address.rm2</name>
<value>node03:8088</value>
</property>
<!-- 指定zk集群地址 -->
<property>
<name>yarn.resourcemanager.zk-address</name>
<value>node01:2181,node02:2181,node03:2181</value>
</property>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<!-- 开启日志聚合 -->
<property>
<name>yarn.log-aggregation-enable</name>
<value>true</value>
</property>
<property>
<name>yarn.log-aggregation.retain-seconds</name>
<value>86400</value>
</property>
<!-- 启用自动恢复 -->
<property>
<name>yarn.resourcemanager.recovery.enabled</name>
<value>true</value>
</property>
<!-- 制定resourcemanager的状态信息存储在zookeeper集群上 -->
<property>
<name>yarn.resourcemanager.store.class</name>
<value>org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore</value>
</property>
<!-- Whether virtual memory limits will be enforced for containers. -->
<property>
<name>yarn.nodemanager.vmem-check-enabled</name>
<value>false</value>
</property>
<property>
<name>yarn.nodemanager.vmem-pmem-ratio</name>
<value>3</value>
</property>

4.4. 拷贝到其他节点

scp yarn-site.xml mapred-site.xml root@node02:`pwd`
scp yarn-site.xml mapred-site.xml root@node03:`pwd`

4.5. 开启集群

[123]zkServer.sh start
[root@node01 hadoop]# start-dfs.sh
[root@node01 hadoop]# start-yarn.sh
[root@node01 hadoop]# mr-jobhistory-daemon.sh start historyserver

4.6. 关机拍摄快照

[1]stop-all.sh
[1]mr-jobhistory-daemon.sh stop historyserver
[123]zkServer.sh stop

5. MR的计算流程

  • 计算1T数据中每个单词出现的次数–> wordcount
  • 在这里插入图片描述

5.1. 原始数据File

  • 1T数据被切分成块存放在HDFS上,每一个块有128M大小

5.2. 数据块Block

  • hdfs上数据存储的一个单元,同一个文件中块的大小都是相同的
  • 因为数据存储到HDFS上不可变,所以有可能块的数量和集群的计算能力不匹配
  • 我们需要一个动态调整本次参与计算节点数量的一个单位
  • 我们可以动态的改变这个单位–》参与的节点

5.3. 切片Split

  • 切片是一个逻辑概念
  • 在不改变现在数据存储的情况下,可以控制参与计算的节点数目
  • 通过切片大小可以达到控制计算节点数量的目的
    • 有多少个切片就会执行多少个Map任务
  • 一般切片大小为Block的整数倍(2 1/2)
    • 防止多余创建和很多的数据连接
  • 如果Split>Block ,计算节点少了
  • 如果Split<Block ,计算节点多了
  • 默认情况下,Split切片的大小等于Block的大小 ,默认128M
  • 一个切片对应一个MapTask

5.4. MapTask

在这里插入图片描述

  • map默认从所属切片读取数据,每次读取一行(默认读取器)到内存中
  • 我们可以根据自己书写的分词逻辑(空格分隔).计算每个单词出现的次数
  • 这是就会产生 (Map<String,Integer>)临时数据,存放在内存中
  • 但是内存大小是有限的,如果多个任务同时执行有可能内存溢出(OOM)
  • 如果把数据都直接存放到硬盘,效率太低
  • 我们需要在OOM和效率低之间提供一个有效方案
    • 可以现在内存中写入一部分,然后写出到硬盘

5.5. 环形数据缓冲区

可以循环利用这块内存区域,减少数据溢写时map的停止时间

  • 每一个Map可以独享的一个内存区域
  • 在内存中构建一个环形数据缓冲区(kvBuffer),默认大小为100M
  • 设置缓冲区的阈值为80%,当缓冲区的数据达到80M开始向外溢写到硬盘
  • 溢写的时候还有20M的空间可以被使用效率并不会被减缓
  • 而且将数据循环写到硬盘,不用担心OOM问题
    在这里插入图片描述

5.6. 分区Partation

  • 根据Key直接计算出对应的Reduce
  • 分区的数量和Reduce的数量是相等的
  • hash(key) % partation = num
  • 默认分区的算法是Hash然后取余
  • Object的hashCode()—equals()
  • 如果两个对象equals,那么两个对象的hashcode一定相等
  • 如果两个对象的hashcode相等,但是对象不一定equlas

5.7. 排序Sort

  • 对要溢写的数据进行排序(QuickSort)
  • 按照先Partation后Key的顺序排序–>相同分区在一起,相同Key的在一起
  • 我们将来溢写出的小文件也都是有序的

5.8. 溢写Spill

  • 将内存中的数据循环写到硬盘,不用担心OOM问题
  • 每次会产生一个80M的文件
  • 如果本次Map产生的数据较多,可能会溢写多个文件

5.9. 合并Merge

  • 因为溢写会产生很多有序(分区 key)的小文件,而且小文件的数目不确定
  • 后面向reduce传递数据带来很大的问题
  • 所以将小文件合并成一个大文件,将来拉取的数据直接从大文件拉取即可
  • 合并小文件的时候同样进行排序(归并排序),最终产生一个有序的大文件

5.10. 组合器combiner

  • 集群的带宽限制了mapreduce作业的数量,因此应该尽量避免map和reduce任务之间的数据传
    输。hadoop允许用户对map的输出数据进行处理,用户可自定义combiner函数(如同map函数和
    reduce函数一般),其逻辑一般和reduce函数一样,combiner的输入是map的输出,combiner
    的输出作为reduce的输入,很多情况下可以直接将reduce函数作为conbiner函数来使用
    (job.setCombinerClass(FlowCountReducer.class);)。
  • combiner属于优化方案,所以无法确定combiner函数会调用多少次,可以在环形缓存区溢出文件
    时调用combiner函数,也可以在溢出的小文件合并成大文件时调用combiner。但要保证不管调用
    几次combiner函数都不会影响最终的结果,所以不是所有处理逻辑都可以使用combiner组件,有
    些逻辑如果在使用了combiner函数后会改变最后rerduce的输出结果(如求几个数的平均值,就不
    能先用combiner求一次各个map输出结果的平均值,再求这些平均值的平均值,这将导致结果错
    误)。
  • combiner的意义就是对每一个maptask的输出进行局部汇总,以减小网络传输量。
    原先传给reduce的数据是 a1 a1 a1 a1 a1
    第一次combiner组合之后变为a{1,1,1,1,…}
    第二次combiner后传给reduce的数据变为a{4,2,3,5…}

5.11. 拉取Fetch

在这里插入图片描述

  • 我们需要将Map的临时结果拉取到Reduce节点
  • 原则:
    • 相同的Key必须拉取到同一个Reduce节点
    • 但是一个Reduce节点可以有多个Key
  • 未排序前拉取数据的时候必须对Map产生的最终的合并文件做全序遍历
    • 而且每一个reduce都要做一个全序遍历
  • 如果map产生的大文件是有序的,每一个reduce只需要从文件中读取自己所需的即可

5.12. 合并Merge

  • 因为reduce拉取的时候,会从多个map拉取数据
  • 那么每个map都会产生一个小文件,这些小文件(文件与文件之间无序,文件内部有序)
  • 为了方便计算(没必要读取N个小文件),需要合并文件
  • 归并算法合并成2个(qishishilia)
  • 相同的key都在一起

5.13. 归并Reduce

  • 将文件中的数据读取到内存中
  • 一次性将相同的key全部读取到内存中
  • 直接将相同的key得到结果–>最终结果

5.14. 写出Output

  • 每个reduce将自己计算的最终结果都会存放到HDFS上

5.15. MapReduce过程截图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

6. MapReduce案例

6.1. WordCount项目

6.1.1. Java实现
  • pom.xml
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<!-- Hadoop版本控制 -->
<hadoop.version>3.1.2</hadoop.version>
<!-- commons-io版本控制 -->
<commons-io.version>2.4</commons-io.version>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoopcommon -->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>${
   
   hadoop.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoophdfs -->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>${
   
   hadoop.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoopclient -->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>${
   
   hadoop.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoopmapreduce-client-common -->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-mapreduce-client-common</artifactId>
<version>${
   
   hadoop.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoopmapreduce-client-core -->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-mapreduce-client-core</artifactId>
<version>${
   
   hadoop.version}<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

♪-Interpretation

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值