文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Hadoop 是什么?它是如何工作的?

2024-11-28 14:14

关注

一、Hadoop是什么?

Hadoop是一个开源的分布式计算框架,用于处理和存储大规模数据集,它是由 Apache Software Foundation维护,能够帮助用户在商用硬件集群上以可靠、高效、容错的方式处理和分析海量数据。为了更好地理解 Hadoop是什么,我们列举了Hadoop一些里程碑:

二、Hadoop的核心组件

Hadoop的核心组件包括以下 4个:

它们的关系如下:

接下来我们将对各个组件进行详细的分析。

1. HDFS

HDFS,全称 Hadoop Distributed File System(分布式文件系统),它是 Hadoop的核心组件之一,旨在解决海量数据的存储问题。

(1) HDFS 架构概述

HDFS是主从结构的分布式文件系统,由两类节点组成:

此外,还有一个可选的组件Secondary NameNode,它用于辅助 NameNode 的元数据备份和日志合并,帮助维持文件系统的高可用性。

HDFS的架构如下图:

(2) 数据存储机制

HDFS的文件是分块存储的,大文件被按照固定大小(默认是 128MB,早期版本是 64MB)划分为多个数据块(Block),每个文件块被存储在集群中的不同 DataNode 上。

为了防止数据因节点故障而丢失,HDFS做了数据冗余与容错机制,它会对每个数据块进行复制,默认情况下每个数据块有 3 副本:

基于上述的副本机制,HDFS可以确保即使部分 DataNode 失效,数据依然可以通过其他存有副本的节点恢复。

(3) 读写操作流程

HDFS 文件写入过程:

HDFS 文件读取过程:

2. MapReduce

MapReduce是 Hadoop的分布式计算框架,通过将复杂的任务分解成多个独立的简单任务来实现并行计算,它的核心思想是“Map”和“Reduce”两个阶段:

(1) MapReduce 执行流程

MapReduce 执行流程包含以下5个步骤:

① Job划分

一个完整的 MapReduce任务称为一个Job,Job是由多个Task构成的,分为Map Task和Reduce Task。

② Input Splitting(输入分片)

MapReduce处理输入数据时,首先将大文件切分成较小的Splits,Map Task的数量通常与输入分片数量一致,每一个Map Task处理一个分片的数据。

③ Map阶段

④ Shuffle and Sort(分发与排序)

Shuffle发生在 Map阶段结束和 Reduce阶段之间,具体过程如下:

⑤ Reduce阶段

整个流程可以用下图解释:

2. YARN

YARN(Yet Another Resource Negotiator,另一种资源调度器)是Hadoop 2.x版本中引入的一个集群资源管理框架,它的设计初衷是解决 Hadoop 1.x中 MapReduce计算框架的资源调度和管理局限性,可以支持各种应用程序调度的需求。

(1) 核心组件

YARN包含以下 5个核心组件:

① ResourceManager

ResourceManager(RM,资源管理器)负责全局集群资源的管理和调度,它是YARN的中央控制器,协调集群中的所有应用和计算资源。ResourceManager有两个重要的子组件:

② NodeManager

NodeManager(NM,节点管理器)是YARN架构中的分布式代理,负责管理每个计算节点上的资源,具体负责:

③ ApplicationMaster

ApplicationMaster(AM,应用程序管理器)是为每个具体应用程序(如MapReduce Job、Spark Job)启动的专用进程,它负责协调整个应用程序生命周期的调度和执行,协调 ResourceManager与 NodeManager,动态申请和释放资源。每一个应用程序在提交时都会启动一个对应的ApplicationMaster实例。 AM的职责包括:

④ Container

Container(容器)是YARN中的资源分配单位,它将逻辑运行环境(如CPU、内存等涉及硬件维度的资源)与应用程序任务绑定在一起。ApplicationMaster可以向ResourceManager申请多个容器,并在这些容器中分配任务进行具体的计算。

⑤ Client

客户端负责与YARN进行交互,提交应用程序请求,并向YARN查询任务的执行进度和结果。客户端将资源需求信息传递给ResourceManager,RM会为该任务分配资源,然后将其控制权交给对应的ApplicationMaster。

核心组件模型如下图:

(2) 工作流程

YARN工作流程包含以下4个步骤:

① 应用程序启动流程

② 资源调度流程

③ 任务运行与监控

一旦任务开始执行,NodeManager会为Container提供隔离的运行环境(如JVM),ApplicationMaster监视任务的运行状态,并通过心跳与NodeManager通信,确保任务成功完成或在出现故障时重新调度任务。

④ 应用完成与资源回收

当ApplicationMaster检测到所有任务均已成功完成,它会向ResourceManager发送一个"完成"信号,表示应用程序已经完成。随后,ResourceManager会通知NodeManager释放任务所占用的资源容器,集群整体资源状态更新。

三、代码实战

在代码实战环节,我们将通过一个完整的示例来展示如何在 Java中实现一个 MapReduce任务,并将处理结果存储回 HDFS。

任务描述:计算给定文件中每个单词出现的次数文件格式:CVS或者JSON项目结构:项目结构如下:

wordcount/
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   ├── WordsCounterMapper.java
│   │   │   ├── WordsCounterReducer.java
│   │   │   └── WordsCounterDriver.java
│   └── resources/
├── input/
│   └── input.cvs
│ input.cvs
└── output/

1.安装Hadoop

我自己Mac电脑安装的是 Hadoop-3.4.1,查看版本指令:hadoop version,关于安装 Hadoop,可以参考这篇文章

2.处理文件

(1) 处理 CSV文件

假设我们有一个超大的 CSV文件:input.csv,如下内容只是展示前几行数据:

id,name,address
1,yuanjava,hangzhou
2,juejin,beijin
3,didi,beijing
...

我们可以使用开源的 Apache Commons CSV工具类来处理该文件,对应的依赖如下:

// maven依赖

    org.apache.commons
    commons-csv
    1.12.0


// gradle 依赖
implementation 'org.apache.commons:commons-csv:1.12.0'

(2) 处理 Json文件

假设我们有一个超大的 Json文件:input.json,如下内容只是展示前几行数据:

[
    {"id": 1, "name": "yuanjava", "address": "hangzhou"},
    {"id": 2, "name": "juejin", "address": "beijing"},
    {"id": 3, "name": "didi", "address": "beijing"},
    ...
]

我们可以使用开源的 Jackson库来处理文件,对应的依赖如下:

// maven依赖

    com.fasterxml.jackson.core
    jackson-databind
    2.18.1


// gradle 依赖
implementation 'com.fasterxml.jackson.core:jackson-databind:2.18.1'

3.增加 Hadoop依赖

// maven依赖

    org.apache.hadoop
    hadoop-common
    3.4.1


    org.apache.hadoop
    hadoop-mapreduce-client-core
    3.4.1


// gradle依赖
implementation 'org.apache.hadoop:hadoop-common:3.4.1'
implementation 'org.apache.hadoop:hadoop-mapreduce-client-core:3.4.1'

4.编写 Mapper类

Mapper类的作用是处理输入数据,并为每个输入记录生成键值对,在词频统计任务中,Mapper 的任务是将每个单词映射为一个中间键值对 (word, 1)。

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVRecord;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;

import java.io.IOException;
import java.io.StringReader;

public class WordsCounterMapper extends Mapper {
    private final static IntWritable one = new IntWritable(1);
    private Text word = new Text();
    private ObjectMapper objectMapper = new ObjectMapper();

    @Override
    protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
        String line = value.toString().trim();

        if (line.isEmpty()) {
            return; // Skip empty lines
        }

        // json以'{'开头, CVS以'['开头
        if (line.startsWith("{") || line.startsWith("[")) {
            processJson(line, context);
        } else {
            processCsv(line, context);
        }
    }

    private void processJson(String line, Context context) throws IOException, InterruptedException{
        JsonNode rootNode = objectMapper.readTree(line);

        if (rootNode.isArray()) {
            for (JsonNode node : rootNode) {
                String name = node.get("name").asText();
                word.set(name);
                context.write(word, one);
            }
        } else if (rootNode.isObject()) {
            String name = rootNode.get("name").asText();
            word.set(name);
            context.write(word, one);
        }
    }

    private void processCsv(String line, Context context) throws IOException, InterruptedException{
        StringReader reader = new StringReader(line);
        Iterable records = CSVFormat.DEFAULT.parse(reader);

        for (CSVRecord record : records) {
            // Assuming the CSV has a header row and "name" is one of the columns
            String name = record.get("name");
            word.set(name);
            context.write(word, one);
        }
    }
}

5.编写 Reducer类

Reducer类的作用是对来自 Mapper的中间键值对进行汇总,在词频统计任务中,Reduce 的任务是对相同单词的计数进行累加。

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import java.io.IOException;

public class WordsCounterDriver {
    public static void main(String[] args){
        if (args.length != 2) {
            System.err.println("Please enter input path and output path.");
            System.exit(-1);
        }

        Configuration conf = new Configuration();
        Job job = Job.getInstance(conf, "wordCounter");

        job.setJarByClass(WordsCounterDriver.class);
        job.setMapperClass(WordsCounterMapper.class);
        job.setReducerClass(WordsCounterReducer.class);

        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);

        FileInputFormat.addInputPath(job, new Path(args[0]));
        FileOutputFormat.setOutputPath(job, new Path(args[1]));

        System.exit(job.waitForCompletion(true) ? 0 : 1);
    }
}

6.编写 Driver 类

Driver 类用于配置 MapReduce 作业并启动作业。它指定了 Mapper 和 Reducer 的实现类,以及输入和输出路径等。

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import java.io.IOException;

public class WordsCounterDriver {
    public static void main(String[] args){
        if (args.length != 2) {
            System.err.println("Please enter input path and output path.");
            System.exit(-1);
        }

        Configuration conf = new Configuration();
        Job job = Job.getInstance(conf, "wordCounter");

        job.setJarByClass(WordsCounterDriver.class);
        job.setMapperClass(WordsCounterMapper.class);
        job.setReducerClass(WordsCounterReducer.class);

        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);

        FileInputFormat.addInputPath(job, new Path(args[0]));
        FileOutputFormat.setOutputPath(job, new Path(args[1]));

        System.exit(job.waitForCompletion(true) ? 0 : 1);
    }
}

7.运行和查看结果

(1) 运行步骤:

hadoop jar wordcounter.jar WordCounterDriver input/input.cvs output/
hadoop jar wordcounter.jar WordCounterDriver input/input.json output/

(2) 查看输出结果

任务完成后,输出结果将会保存在指定的输出目录中,我们可以使用以下命令查看结果:

hadoop fs -cat output/part-r-00000

输出结果可能如下:

yuanjava 100
juejin 3000
didi 100
...

8.代码解释与优化

(1) Mapper详解

继承与泛型:Mapper 表示输入键值对的类型和输出键值对的类型。输入键是行偏移量,值是行文本,输出键是单词,值是整数 1。

map 方法:对每一行文本进行分割,然后对每个单词输出一个键值对。

(2) Reducer详解

继承与泛型:Reducer 表示输入和输出键值对类型。输入键是单词,值是整数列表,输出键是单词,值是单词的累加计数。

reduce 方法:对每个单词的所有计数进行累加输出。

(3) Driver详解

Job 配置:设置 Mapper和 Reducer类,指定输入输出格式。

路径设置:通过命令行参数指定输入输出路径。

(4) 优化建议

通过这个简单的例子,我们展示了如何在 Java中实现一个基本的 MapReduce程序,通过定义 Mapper和 Reducer 再结合 Driver,能够实现对大规模数据集的分布式处理。如果要处理更复杂的任务,可以通过自定义分区器、排序规则、Combiner 等方式进行优化。

通过此示例,我们可以更好地理解 Hadoop MapReduce 的工作原理和编程模型以及它对于大数据处理的重要性。

四、总结

本文,我们分析了 Hadoop的核心组件及其工作原理,让我们对 Hadoop有了一定的认识。本人有几年 Hadoop的使用经验,从整体上看,Hadoop的使用属于中等难度,Hadoop的生态比完善,学习难度比较大,但是,不得不说 Hadoop的设计思维很优秀,值得我们花时间去学习。

2003年,Google发布 Google File System(GFS)、MapReduce和 Bigtable 三篇论文后,Doug Cutting和 Michael J. Cafarella抓住了机会,共同创造了 Hadoop。Google的这三篇经典论文是大数据领域的经典之作,但它的影响力远不止大数据领域,因此,如果想成为一名优秀的工程师,阅读原滋原味的优秀论文绝对是受益无穷的一种方式。

Hadoop展示了大数据领域一个优秀的架构模式:集中管理,分布式存储与计算。这种优秀的架构模式同样还运用在 Spark、Kafka、Flink、HBase、Elasticsearch、Cassandra等这些优秀的框架上,它在大数据领域展示了显著的优势。

最近一年,我从事的项目有幸和 MIT,Standford这样顶尖学府出来的工程师合作,他们强悍的数学建模能力以及对同一个问题思考的深度确实让我望尘莫及,在互联网大厂卷了这么多年,每天都有写完的需求开不完的会,绝大多数程序员都被业务裹挟着,导致很多优秀的人无法从业务中抽离出来去研究更深层领域的东西,陷入无尽的内卷。

如何在这个内卷的环境中让自己立于不败之地?基本功绝对是重中之重。

最后,因为 Hadoop的内容太多,很难仅凭本文把 Hadoop讲透,希望在分享我个人对 Hadoop理解的同时也能抛砖引玉,激发同行写出更多优秀的文章,对于技术,对于行业产生共多思考的共鸣。

来源:猿java内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯