3. Hadoop生态圈:HDFS架构、YARN资源调度、Hadoop集群搭建实战

好,咱们进入第三章。这一章可以说是Hadoop的“硬核”部分。Hadoop生态圈很大,但核心就三块:存数据的HDFS、算数据的MapReduce(后面细讲)、管资源的YARN。今天咱们先把HDFS和YARN这两个“骨架”讲透,再手把手搭一个集群。

我个人习惯,学分布式系统,先搞懂“数据怎么存”和“任务怎么跑”。这两件事搞明白了,后面学Spark、Flink都轻松很多。

3.1 HDFS架构:数据是怎么存起来的?

HDFS,全称Hadoop Distributed File System。说白了,就是把一个大文件切成很多小块,分散存到一堆廉价的服务器上。

你想想看,一个100TB的文件,单台机器根本存不下。就算存下了,读写速度也慢得让人崩溃。HDFS的做法是:切成128MB的块,每个块存3份副本,分散到不同机器上。

3.1.1 核心角色:NameNode 和 DataNode

HDFS里有两个核心角色:

  • NameNode(老大):管元数据。它知道每个文件被切成了多少块,每个块存在哪几台机器上。但它不存实际数据。
  • DataNode(小弟):管实际数据。每个DataNode上存着一些数据块,定期向NameNode汇报“我还活着,我这里有这些块”。

我在项目中遇到过一个问题:NameNode挂了,整个集群就瘫痪了。因为客户端找不到数据在哪。所以生产环境一定要给NameNode做高可用,这个后面会讲。

关键点:NameNode是HDFS的“大脑”,它挂了,整个HDFS就不可用。DataNode挂了,只要副本数够,数据不会丢。

3.1.2 数据写入流程

客户端要写一个200MB的文件到HDFS,流程是这样的:

  1. 客户端向NameNode请求“我要写一个文件,叫/data/test.log”
  2. NameNode检查权限和路径,没问题就返回“可以写,我给你分配3个DataNode”
  3. 客户端把文件切成128MB+72MB两个块,分别写入分配的DataNode
  4. 写入时,数据会流水线式地复制到其他副本节点
  5. 所有块写完后,客户端通知NameNode“写完了”

嗯,这里要注意:HDFS是“一次写入,多次读取”的设计。不支持随机修改文件内容。你想想看,如果支持随机修改,那分布式系统的数据一致性就太复杂了。

3.1.3 数据读取流程

读取就简单多了:

  1. 客户端问NameNode:“我要读/data/test.log,块都在哪?”
  2. NameNode返回块的位置列表(比如块1在node1、node2、node3)
  3. 客户端就近读取数据(优先读同机架的副本)

小技巧:HDFS会尽量让客户端读取离它最近的副本。如果你把计算任务也部署在DataNode上,数据本地性会非常好,省去网络传输的开销。我曾经优化过一个任务,就是把计算节点和数据节点混部,性能提升了30%。

3.2 YARN资源调度:任务是怎么跑起来的?

HDFS解决了数据存储问题,那计算任务谁来管?这就是YARN的活了。

YARN,全称Yet Another Resource Negotiator。说白了,就是一个资源调度系统。你的MapReduce任务、Spark任务、Flink任务,都跑在YARN上面。

3.2.1 YARN的核心组件

组件 角色 职责
ResourceManager (RM) 全局老大 管理集群资源,接收客户端请求,调度任务
NodeManager (NM) 每台机器的小弟 管理本机资源(CPU、内存),执行RM分配的容器
ApplicationMaster (AM) 每个任务的管家 负责一个任务的整个生命周期,向RM申请资源
Container 资源容器 封装了CPU、内存等资源,任务就在容器里跑

我记得刚开始学YARN时,总觉得ApplicationMaster这个概念很绕。后来想明白了:每个任务都有一个专属的“管家”,这个管家负责跟RM要资源、监控任务进度。任务跑完了,管家就自动退出。

3.2.2 任务提交流程

一个MapReduce任务提交到YARN,流程是这样的:

  1. 客户端提交任务到ResourceManager
  2. RM在某个NodeManager上启动一个Container,里面运行ApplicationMaster
  3. AM向RM申请资源(要多少个Container,每个要多少CPU和内存)
  4. RM分配资源,AM在对应的NodeManager上启动Container
  5. Container里运行Map或Reduce任务
  6. 任务完成后,AM向RM注销自己,释放所有资源

避坑指南:我曾经遇到过一个问题,集群里跑了很多小任务,每个任务只申请1个Container,但每个Container都要启动一个JVM。结果JVM启动的开销比任务本身还大。后来我调整了参数,把小任务合并成大任务,性能提升明显。

3.2.3 调度策略

YARN支持多种调度策略,常用的有三种:

  • FIFO Scheduler:先进先出,简单粗暴。但容易造成大任务阻塞小任务。
  • Capacity Scheduler:按队列分配资源。每个队列有固定的资源上限,互不干扰。生产环境最常用。
  • Fair Scheduler:公平调度。所有任务平分资源,大任务和小任务都能得到响应。

我个人习惯用Capacity Scheduler。把不同业务线分到不同队列,互不影响。比如离线任务一个队列,实时任务一个队列,互不抢资源。

3.3 Hadoop集群搭建实战

理论讲完了,咱们动手搭一个集群。我假设你有3台机器,每台机器4核CPU、8GB内存。操作系统是CentOS 7。

3.3.1 环境准备

先做几件事:

  1. 配置hosts文件,让三台机器能互相通过主机名访问
  2. 配置SSH免密登录(从主节点到所有节点)
  3. 安装JDK 8(Hadoop 3.x需要JDK 8以上)
  4. 关闭防火墙和SELinux
# 配置hosts
192.168.1.10 hadoop01
192.168.1.11 hadoop02
192.168.1.12 hadoop03

# 生成SSH密钥
ssh-keygen -t rsa -P ''
ssh-copy-id hadoop01
ssh-copy-id hadoop02
ssh-copy-id hadoop03

3.3.2 下载并配置Hadoop

从Apache官网下载Hadoop 3.3.6,解压到/opt/hadoop目录。

# 配置hadoop-env.sh
export JAVA_HOME=/usr/local/jdk8

# 配置core-site.xml
<configuration>
  <property>
    <name>fs.defaultFS</name>
    <value>hdfs://hadoop01:9000</value>
  </property>
</configuration>

# 配置hdfs-site.xml
<configuration>
  <property>
    <name>dfs.replication</name>
    <value>3</value>
  </property>
  <property>
    <name>dfs.namenode.name.dir</name>
    <value>/data/hadoop/namenode</value>
  </property>
  <property>
    <name>dfs.datanode.data.dir</name>
    <value>/data/hadoop/datanode</value>
  </property>
</configuration>

# 配置yarn-site.xml
<configuration>
  <property>
    <name>yarn.resourcemanager.hostname</name>
    <value>hadoop01</value>
  </property>
  <property>
    <name>yarn.nodemanager.resource.memory-mb</name>
    <value>6144</value>
  </property>
  <property>
    <name>yarn.nodemanager.resource.cpu-vcores</name>
    <value>3</value>
  </property>
</configuration>

经验之谈:yarn.nodemanager.resource.memory-mb这个参数,我建议不要设满。比如机器有8GB内存,留2GB给操作系统和其他进程,YARN最多用6GB。否则内存不够用,NodeManager会被系统杀掉。

3.3.3 配置workers文件

在/opt/hadoop/etc/hadoop/workers文件中,写上所有DataNode的主机名:

hadoop01
hadoop02
hadoop03

3.3.4 启动集群

# 格式化NameNode(只在第一次启动时执行)
hdfs namenode -format

# 启动HDFS
start-dfs.sh

# 启动YARN
start-yarn.sh

# 验证
jps
# 应该看到:NameNode, DataNode, ResourceManager, NodeManager

启动后,访问 http://hadoop01:9870 可以看到HDFS的Web界面。访问 http://hadoop01:8088 可以看到YARN的Web界面。

3.3.5 跑一个测试任务

# 创建一个测试目录
hdfs dfs -mkdir /test

# 上传一个文件
hdfs dfs -put /etc/hosts /test/

# 跑一个WordCount示例
hadoop jar /opt/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.3.6.jar wordcount /test/hosts /test/output

如果能看到Map和Reduce任务成功执行,恭喜你,Hadoop集群搭建成功了!

总结一下:HDFS负责存数据,YARN负责跑任务。两者配合,构成了Hadoop生态圈的基石。后面学Spark、Hive、HBase,都是在这两个组件之上构建的。

嗯,这一章内容不少。HDFS的架构、YARN的调度、集群搭建,每一步都有坑。我当年第一次搭集群,光SSH免密就折腾了半天。别急,多练几次就熟了。下一章咱们讲MapReduce计算框架,看看数据到底是怎么被处理的。