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,流程是这样的:
- 客户端向NameNode请求“我要写一个文件,叫/data/test.log”
- NameNode检查权限和路径,没问题就返回“可以写,我给你分配3个DataNode”
- 客户端把文件切成128MB+72MB两个块,分别写入分配的DataNode
- 写入时,数据会流水线式地复制到其他副本节点
- 所有块写完后,客户端通知NameNode“写完了”
嗯,这里要注意:HDFS是“一次写入,多次读取”的设计。不支持随机修改文件内容。你想想看,如果支持随机修改,那分布式系统的数据一致性就太复杂了。
3.1.3 数据读取流程
读取就简单多了:
- 客户端问NameNode:“我要读/data/test.log,块都在哪?”
- NameNode返回块的位置列表(比如块1在node1、node2、node3)
- 客户端就近读取数据(优先读同机架的副本)
小技巧: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,流程是这样的:
- 客户端提交任务到ResourceManager
- RM在某个NodeManager上启动一个Container,里面运行ApplicationMaster
- AM向RM申请资源(要多少个Container,每个要多少CPU和内存)
- RM分配资源,AM在对应的NodeManager上启动Container
- Container里运行Map或Reduce任务
- 任务完成后,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 环境准备
先做几件事:
- 配置hosts文件,让三台机器能互相通过主机名访问
- 配置SSH免密登录(从主节点到所有节点)
- 安装JDK 8(Hadoop 3.x需要JDK 8以上)
- 关闭防火墙和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计算框架,看看数据到底是怎么被处理的。