跳到主要内容

Hadoop 基础

Hadoop是Apache基金会开发的开源分布式计算平台,是大数据技术的基石。它提供了可靠的分布式存储(HDFS)和分布式计算(MapReduce)能力,能够处理PB级别的海量数据。

Hadoop 概述

什么是 Hadoop?

Hadoop是一个由Apache基金会开发的分布式系统基础架构,主要解决海量数据的存储和分析计算问题。用户可以在不了解分布式底层细节的情况下,开发分布式程序,利用集群的威力进行高速运算和存储。

Hadoop的核心设计目标是:

  1. 高可靠性:通过数据多副本和自动故障转移机制保证数据安全
  2. 高扩展性:可以通过增加节点线性扩展集群容量
  3. 高效性:采用分布式并行计算,加快处理速度
  4. 高容错性:自动将失败的任务重新分配

Hadoop 三大核心组件

Hadoop由三个核心组件构成,它们各司其职又紧密协作:

组件全称功能
HDFSHadoop Distributed File System分布式文件存储
MapReduceMapReduce分布式计算框架
YARNYet Another Resource Negotiator资源调度管理

Hadoop 版本演进

版本特点
Hadoop 1.xHDFS + MapReduce,计算和资源调度耦合
Hadoop 2.x引入YARN,实现资源调度与计算分离
Hadoop 3.x支持纠删码、多NameNode、容器化优化

HDFS 分布式文件系统

HDFS(Hadoop Distributed File System)是Hadoop的分布式文件存储系统,设计用于在通用硬件上运行,提供高吞吐量的数据访问。

HDFS 设计目标

  1. 适合大文件存储:适合存储GB到TB级别的大文件
  2. 流式数据访问:一次写入,多次读取的数据访问模式
  3. 商用硬件:运行在普通服务器上,通过冗余保证可靠性
  4. 高容错:自动处理节点故障,数据自动复制

HDFS 架构

HDFS采用主从架构(Master-Slave),主要由以下组件构成:

NameNode(名称节点)

NameNode是HDFS的主节点,负责管理文件系统的元数据:

  • 文件目录树:维护整个文件系统的目录结构
  • 文件块映射:记录每个文件由哪些数据块组成
  • 数据块位置:记录每个数据块存储在哪些DataNode上
  • 访问控制:管理文件的权限信息

NameNode将元数据保存在内存中以提高访问速度,同时持久化到磁盘的FsImage和EditLog文件中。

DataNode(数据节点)

DataNode是HDFS的工作节点,负责实际的数据存储:

  • 数据块存储:将文件切分成固定大小的块(默认128MB)存储
  • 数据块读写:响应客户端的读写请求
  • 心跳汇报:定期向NameNode发送心跳和块报告
  • 数据块复制:根据NameNode指令复制数据块

Secondary NameNode(辅助节点)

Secondary NameNode不是NameNode的热备,它的主要作用是:

  • 合并FsImage和EditLog:定期合并元数据,减少EditLog大小
  • 检查点创建:创建元数据检查点,加快NameNode启动
  • 元数据备份:提供元数据的冷备份

HDFS 文件读写流程

文件读取流程

客户端读取HDFS文件的步骤如下:

  1. 客户端调用FileSystem.open()打开文件
  2. NameNode返回文件块位置信息
  3. 客户端连接最近的DataNode读取数据
  4. 读取完成后关闭连接
// HDFS文件读取示例
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(conf);

Path filePath = new Path("/user/data/example.txt");
FSDataInputStream inputStream = fs.open(filePath);

BufferedReader reader = new BufferedReader(
new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}

reader.close();
fs.close();

文件写入流程

客户端写入HDFS文件的步骤如下:

  1. 客户端调用FileSystem.create()创建文件
  2. NameNode检查权限并创建文件元数据
  3. 客户端将数据写入数据队列
  4. DataNode组成管道,依次写入数据块
  5. 写入完成后,客户端调用close()关闭文件
// HDFS文件写入示例
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(conf);

Path filePath = new Path("/user/data/output.txt");
FSDataOutputStream outputStream = fs.create(filePath);

String content = "Hello, HDFS!";
outputStream.write(content.getBytes());

outputStream.close();
fs.close();

HDFS 常用命令

HDFS提供了丰富的命令行工具,用于文件操作:

# 查看帮助
hdfs dfs -help

# 创建目录
hdfs dfs -mkdir -p /user/hadoop/data

# 上传文件
hdfs dfs -put localfile.txt /user/hadoop/data/

# 下载文件
hdfs dfs -get /user/hadoop/data/remotefile.txt ./

# 列出目录内容
hdfs dfs -ls /user/hadoop/data/

# 查看文件内容
hdfs dfs -cat /user/hadoop/data/file.txt

# 删除文件或目录
hdfs dfs -rm -r /user/hadoop/data/olddir

# 查看文件大小
hdfs dfs -du -h /user/hadoop/data/

# 设置副本数
hdfs dfs -setrep 3 /user/hadoop/data/file.txt

HDFS 数据块与副本

数据块(Block)

HDFS将文件切分成固定大小的块进行存储:

  • 默认块大小:128MB(Hadoop 2.x/3.x)
  • 设计原因:减少元数据占用、减少寻址时间、支持大文件

副本机制

HDFS通过多副本机制保证数据可靠性:

  • 默认副本数:3
  • 副本放置策略
    • 第一个副本:优先放在客户端所在节点
    • 第二个副本:放在不同机架的节点
    • 第三个副本:放在第二个副本同机架的不同节点

MapReduce 分布式计算框架

MapReduce是一种分布式计算编程模型,将复杂的分布式计算分解为Map(映射)和Reduce(归约)两个阶段。

MapReduce 编程模型

MapReduce的核心思想是将计算任务分解为两个阶段:

  1. Map阶段:将输入数据映射为键值对,进行并行处理
  2. Reduce阶段:对Map输出的中间结果进行汇总
输入数据 -> Map -> (K1, V1) -> Shuffle -> (K2, List<V2>) -> Reduce -> 输出结果

MapReduce 工作流程

完整的MapReduce执行流程包括以下步骤:

  1. 输入分片:将输入文件切分成多个分片(Split)
  2. Map任务:每个分片启动一个Map任务处理
  3. Shuffle过程:对Map输出进行分区、排序、合并
  4. Reduce任务:对Shuffle后的数据进行汇总
  5. 输出结果:将Reduce结果写入HDFS

WordCount 示例

WordCount是MapReduce的经典入门示例,统计文本中单词出现的次数:

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 org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import java.io.IOException;

// Mapper类:输入偏移量和行内容,输出单词和计数1
public class WordCountMapper
extends Mapper<LongWritable, Text, Text, IntWritable> {

private final static IntWritable one = new IntWritable(1);
private Text word = new Text();

@Override
protected void map(LongWritable key, Text value, Context context)
throws IOException, InterruptedException {
// 将每行文本按空格分割成单词
String[] words = value.toString().split("\\s+");
for (String w : words) {
word.set(w);
// 输出 (单词, 1)
context.write(word, one);
}
}
}

// Reducer类:汇总每个单词的出现次数
public class WordCountReducer
extends Reducer<Text, IntWritable, Text, IntWritable> {

private IntWritable result = new IntWritable();

@Override
protected void reduce(Text key, Iterable<IntWritable> values,
Context context) throws IOException, InterruptedException {
int sum = 0;
// 累加所有值
for (IntWritable val : values) {
sum += val.get();
}
result.set(sum);
// 输出 (单词, 总次数)
context.write(key, result);
}
}

// Driver类:配置和提交作业
public class WordCountDriver {

public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
Job job = Job.getInstance(conf, "word count");

// 设置作业类
job.setJarByClass(WordCountDriver.class);
job.setMapperClass(WordCountMapper.class);
job.setReducerClass(WordCountReducer.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);
}
}

Shuffle 机制详解

Shuffle是MapReduce中最核心的过程,它连接Map和Reduce阶段:

Map端Shuffle

  1. 环形缓冲区:Map输出先写入内存缓冲区(默认100MB)
  2. 溢写:缓冲区达到阈值(80%)时,溢写到磁盘
  3. 分区排序:溢写过程中按分区和键排序
  4. 合并:多个溢写文件合并成一个大文件

Reduce端Shuffle

  1. 拉取数据:Reduce从Map节点拉取属于自己的分区数据
  2. 合并:将拉取的数据合并排序
  3. 分组:相同Key的数据分到一组

MapReduce 数据类型

MapReduce使用Writable接口实现序列化:

数据类型Java类型说明
IntWritableint整型
LongWritablelong长整型
FloatWritablefloat浮点型
DoubleWritabledouble双精度
TextString文本
BooleanWritableboolean布尔型
NullWritablenull空值

YARN 资源调度

YARN(Yet Another Resource Negotiator)是Hadoop 2.x引入的资源管理系统,负责集群资源的统一管理和调度。

YARN 架构

YARN采用主从架构,主要组件包括:

ResourceManager

ResourceManager是YARN的主节点,负责整个集群的资源管理:

  • 资源调度:根据调度策略分配资源
  • 应用管理:接收和管理应用程序提交
  • 状态监控:监控集群资源使用情况

NodeManager

NodeManager是每个节点上的代理,负责单个节点的资源管理:

  • 资源汇报:向ResourceManager汇报节点资源状态
  • 容器管理:启动和监控容器
  • 资源隔离:保证容器间的资源隔离

ApplicationMaster

ApplicationMaster是每个应用程序的管理者:

  • 任务切分:将应用切分成多个任务
  • 资源申请:向ResourceManager申请资源
  • 任务调度:在分配的容器上调度任务
  • 容错处理:处理任务失败和重试

Container

Container是YARN中资源抽象,封装了:

  • CPU:虚拟CPU核心数
  • 内存:可用内存大小
  • 其他资源:磁盘、网络等

YARN 工作流程

应用程序在YARN上的执行流程:

  1. 客户端向ResourceManager提交应用
  2. ResourceManager分配第一个Container
  3. 在Container中启动ApplicationMaster
  4. ApplicationMaster向ResourceManager注册并申请资源
  5. ResourceManager返回可用的Container列表
  6. ApplicationMaster与NodeManager通信启动任务
  7. 任务执行完成,ApplicationMaster注销

YARN 调度器

YARN支持多种调度策略:

FIFO调度器

  • 先进先出,简单但效率低
  • 不适合多用户共享集群

容量调度器(Capacity Scheduler)

  • 将集群资源划分为多个队列
  • 每个队列有保证的资源配额
  • 支持多租户,适合企业环境

公平调度器(Fair Scheduler)

  • 所有应用公平获得资源
  • 支持资源抢占
  • 适合多用户交互式应用

Hadoop 集群部署

部署模式

Hadoop支持三种部署模式:

模式说明适用场景
单机模式单进程运行,无分布式特性学习、调试
伪分布式单机模拟分布式环境开发、测试
完全分布式多机集群部署生产环境

核心配置文件

Hadoop的主要配置文件位于$HADOOP_HOME/etc/hadoop/目录:

core-site.xml

<configuration>
<!-- 指定HDFS的NameNode地址 -->
<property>
<name>fs.defaultFS</name>
<value>hdfs://namenode:9000</value>
</property>
<!-- 指定Hadoop临时目录 -->
<property>
<name>hadoop.tmp.dir</name>
<value>/data/hadoop/tmp</value>
</property>
</configuration>

hdfs-site.xml

<configuration>
<!-- 副本数量 -->
<property>
<name>dfs.replication</name>
<value>3</value>
</property>
<!-- NameNode数据目录 -->
<property>
<name>dfs.namenode.name.dir</name>
<value>/data/hadoop/namenode</value>
</property>
<!-- DataNode数据目录 -->
<property>
<name>dfs.datanode.data.dir</name>
<value>/data/hadoop/datanode</value>
</property>
</configuration>

yarn-site.xml

<configuration>
<!-- ResourceManager地址 -->
<property>
<name>yarn.resourcemanager.hostname</name>
<value>resourcemanager</value>
</property>
<!-- NodeManager运行的辅助服务 -->
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
</configuration>

mapred-site.xml

<configuration>
<!-- 指定MapReduce运行在YARN上 -->
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
</configuration>

集群启动流程

# 1. 格式化NameNode(仅首次)
hdfs namenode -format

# 2. 启动HDFS
start-dfs.sh

# 3. 启动YARN
start-yarn.sh

# 4. 查看进程
jps

# 5. 访问Web界面
# HDFS: http://namenode:9870
# YARN: http://resourcemanager:8088

Hadoop 高可用

生产环境中,Hadoop集群需要高可用(HA)配置,避免单点故障。

HDFS 高可用

HDFS高可用通过Active/Standby NameNode实现:

  1. 主备切换:Active NameNode故障时,Standby自动接管
  2. 共享存储:使用Quorum Journal Manager或NFS共享EditLog
  3. ZooKeeper协调:自动故障检测和主备选举

YARN 高可用

YARN高可用通过ResourceManager HA实现:

  1. 主备切换:Active RM故障时,Standby RM接管
  2. 状态恢复:Standby RM从ZooKeeper恢复应用状态
  3. 透明切换:客户端自动重连到新的Active RM

小结

本章介绍了Hadoop的核心组件和基本使用:

  1. HDFS:分布式文件系统,提供高可靠的文件存储
  2. MapReduce:分布式计算框架,适合离线批处理
  3. YARN:资源调度系统,管理集群资源分配

Hadoop是大数据技术的基础,理解其原理对于学习后续的Spark、Flink等框架非常重要。在实际应用中,Hadoop通常与Hive、HBase等组件配合使用,构建完整的大数据处理平台。