前言:一个关于"抢资源"的故事
在讲YARN之前,让我先讲一个真实的故事。
那是Hadoop 1.x的时代,我们公司有一个50台机器的Hadoop集群。某天,数据组的小王提交了一个MapReduce任务,跑全年的用户行为分析;与此同时,算法组的小李也提交了一个任务,训练推荐模型。
然后,整个集群就陷入了混乱——两个任务疯狂抢资源,互相等待,谁也跑不完。
更惨的是,运维组的老张想跑一个Spark任务做实时监控,但是——对不起,Hadoop 1.x只支持MapReduce,不支持Spark。
老张当场表演了一个原地裂开。
"如果有一个统一的资源管理系统,能管理所有类型的计算任务,该多好啊……"
于是,YARN诞生了。
本篇是Hadoop系列的最后一篇,我们将学习:
- YARN:Hadoop的资源管理系统
- Hadoop生态圈:大象的朋友们
让我们开始最后的冲刺!
一、从Hadoop 1.x到2.x:架构的进化
1.1 Hadoop 1.x的架构问题
graph TB
subgraph Hadoop1["😰 Hadoop 1.x 架构"]
subgraph MRv1["MapReduce v1"]
JT[JobTracker<br/>作业调度 + 资源管理<br/>一个人干两份活]
TT1[TaskTracker1]
TT2[TaskTracker2]
TT3[TaskTracker3]
end
subgraph HDFS1["HDFS"]
NN[NameNode]
DN1[DataNode1]
DN2[DataNode2]
end
JT --> TT1
JT --> TT2
JT --> TT3
end
subgraph 问题["⚠️ 存在的问题"]
P1[1. JobTracker单点故障<br/>挂了全完蛋]
P2[2. JobTracker负担太重<br/>既管资源又管调度]
P3[3. 只支持MapReduce<br/>想跑Spark?没门]
P4[4. 资源利用率低<br/>slot固定分配]
end
style JT fill:#ff6b6b
style P1 fill:#ff6b6b
style P2 fill:#ff6b6b
style P3 fill:#ff6b6b
style P4 fill:#ff6b6b
Hadoop 1.x的核心问题就是:JobTracker一个人干了太多活,又要管理集群资源,又要调度MapReduce任务。这就像让一个程序员既写代码又做产品又搞运维还要兼职HR——迟早要猝死。
1.2 Hadoop 2.x的解决方案:YARN
Hadoop 2.x做了一个聪明的决定:把资源管理和作业调度分开。
graph TB
subgraph Hadoop2["✅ Hadoop 2.x 架构"]
subgraph YARN["YARN (资源管理)"]
RM[ResourceManager<br/>全局资源管理]
NM1[NodeManager1]
NM2[NodeManager2]
NM3[NodeManager3]
end
subgraph Apps["应用层 (各种计算框架)"]
MR[MapReduce]
Spark[Spark]
Flink[Flink]
Tez[Tez]
end
subgraph HDFS2["HDFS"]
NN[NameNode]
DN1[DataNode1]
DN2[DataNode2]
end
Apps --> YARN
YARN --> HDFS2
end
subgraph 优势["🎉 改进"]
A1[1. 资源管理与作业调度分离]
A2[2. 支持多种计算框架]
A3[3. 资源利用率提高]
A4[4. 可扩展性更强]
end
style RM fill:#4ecdc4
style A1 fill:#4ecdc4
style A2 fill:#4ecdc4
style A3 fill:#4ecdc4
style A4 fill:#4ecdc4
YARN = Yet Another Resource Negotiator(又一个资源协调者)
这个名字起得很谦虚——"又一个",但它确实彻底改变了Hadoop的命运。
二、YARN架构详解
2.1 核心组件
graph TB
subgraph YARN架构["🏗️ YARN架构全景图"]
subgraph 全局["全局组件"]
RM[ResourceManager<br/>资源管理者<br/>大管家]
end
subgraph RM内部["ResourceManager内部"]
Scheduler[Scheduler<br/>调度器<br/>只负责分配资源]
ASM[ApplicationsManager<br/>应用管理器<br/>管理所有应用]
end
subgraph 节点["每个节点"]
NM1[NodeManager<br/>节点管理器<br/>管理单个节点资源]
NM2[NodeManager]
NM3[NodeManager]
end
subgraph 应用["每个应用"]
AM1[ApplicationMaster<br/>应用主管<br/>管理单个应用]
C1[Container<br/>资源容器]
C2[Container]
C3[Container]
end
RM --> Scheduler
RM --> ASM
RM --> NM1
RM --> NM2
RM --> NM3
ASM --> AM1
AM1 --> C1
AM1 --> C2
AM1 --> C3
NM1 -.-> C1
NM2 -.-> C2
NM3 -.-> C3
end
style RM fill:#ff6b6b,stroke:#333,stroke-width:2px
style NM1 fill:#4ecdc4
style NM2 fill:#4ecdc4
style NM3 fill:#4ecdc4
style AM1 fill:#ffe66d
style C1 fill:#95a5a6
style C2 fill:#95a5a6
style C3 fill:#95a5a6
2.2 各组件职责详解
ResourceManager(RM):大管家
graph TB
subgraph RM["🎩 ResourceManager"]
subgraph 调度器["Scheduler 调度器"]
S1[根据策略分配资源]
S2[不监控应用状态]
S3[不负责重启失败任务]
S4[纯粹的资源分配器]
end
subgraph 应用管理器["ApplicationsManager"]
A1[接收作业提交]
A2[为应用分配第一个Container]
A3[启动ApplicationMaster]
A4[监控AM,失败时重启]
end
end
style 调度器 fill:#ff6b6b
style 应用管理器 fill:#4ecdc4
ResourceManager的哲学:我只管分配资源,具体怎么用是你的事。
这就像公司的财务部门:你申请预算,我审批拨款,但钱怎么花是你项目组自己的事。
NodeManager(NM):节点保姆
graph TB
subgraph NM["👷 NodeManager职责"]
N1[管理单个节点的资源]
N2[定期向RM汇报资源使用情况]
N3[接收并处理来自AM的Container请求]
N4[监控Container的资源使用]
N5[杀死超出资源限制的Container]
end
subgraph 汇报内容["📊 心跳汇报内容"]
H1[节点健康状态]
H2[Container运行状态]
H3[可用资源量]
end
N2 --> H1
N2 --> H2
N2 --> H3
style NM fill:#4ecdc4
NodeManager的哲学:我就是个包工头,管好我这一亩三分地。
ApplicationMaster(AM):应用管家
graph TB
subgraph AM["🎯 ApplicationMaster职责"]
A1[与RM协商获取资源]
A2[与NM通信启动/停止Container]
A3[监控任务执行状态]
A4[处理任务失败,重新申请资源]
A5[向RM报告应用进度]
end
subgraph Features["💡 关键特点"]
T1[每个应用有自己的AM]
T2[AM运行在Container中]
T3[AM是应用的大脑]
T4[不同框架有不同的AM实现]
end
A1 ~~~ T1
style A1 fill:#ffe66d
style A2 fill:#ffe66d
style A3 fill:#ffe66d
style A4 fill:#ffe66d
style A5 fill:#ffe66d
ApplicationMaster的哲学:我的应用我做主,需要什么资源我去要。
这是YARN最精妙的设计——每个应用有自己的管家。MapReduce有MapReduce的AM,Spark有Spark的AM,各管各的,互不干扰。
Container:资源容器
graph LR
subgraph Container["📦 Container"]
C[Container<br/>资源抽象]
subgraph 包含["包含资源"]
R1[CPU核数]
R2[内存大小]
R3[磁盘空间]
R4[网络带宽]
end
subgraph 特点["特点"]
F1[动态分配]
F2[隔离执行]
F3[可以运行任何程序]
end
end
C --> R1
C --> R2
C --> R3
C --> R4
style C fill:#95a5a6
Container的本质:就是一个资源的"盒子",里面装着CPU和内存,你的任务就在这个盒子里运行。
2.3 YARN作业提交流程
让我们看看一个MapReduce作业是如何在YARN上运行的:
sequenceDiagram
participant Client as 客户端
participant RM as ResourceManager
participant NM as NodeManager
participant AM as ApplicationMaster
participant HDFS as HDFS
Note over Client,HDFS: 阶段1:作业提交
Client->>HDFS: 1. 上传作业资源(JAR、配置、分片信息)
Client->>RM: 2. 提交应用
Note over RM,AM: 阶段2:启动ApplicationMaster
RM->>RM: 3. 为应用分配唯一ID
RM->>NM: 4. 在某个节点分配Container
NM->>AM: 5. 启动ApplicationMaster
AM->>HDFS: 6. 下载作业资源
AM->>AM: 7. 初始化,计算需要多少Map/Reduce Task
Note over AM,NM: 阶段3:申请资源运行任务
AM->>RM: 8. 注册 + 申请Container资源
RM->>AM: 9. 分配Container列表
AM->>NM: 10. 通知NM启动Container
NM->>NM: 11. 下载资源,启动任务
Note over AM,Client: 阶段4:任务执行与监控
loop 任务运行中
NM->>AM: 12. 报告任务进度和状态
AM->>RM: 13. 报告应用进度
Client->>RM: 14. 查询应用状态
end
Note over AM,RM: 阶段5:作业完成
AM->>RM: 15. 注销,释放资源
RM->>RM: 16. 清理应用信息
用大白话复述一遍:
| 步骤 | 发生了什么 | 类比 |
|---|
| 1-2 | 客户端把代码和数据传上去,然后告诉RM:"我要跑一个任务" | 向公司提交项目申请 |
| 3-7 | RM找一台机器启动AM,AM开始规划任务 | HR给你分配一个项目经理 |
| 8-11 | AM向RM要资源,拿到后通知NM启动任务 | 项目经理申请预算和人力 |
| 12-14 | 任务跑着,各方互相汇报进度 | 项目周报 |
| 15-16 | 任务完成,资源释放 | 项目结项,人员释放 |
三、YARN调度器:资源怎么分?
3.1 三种调度器对比
YARN支持三种调度器,解决的核心问题是:集群资源有限,多个应用抢资源,怎么分配?
graph TB
subgraph 调度器对比["🎯 三种调度器对比"]
subgraph FIFO["FIFO Scheduler"]
F1[先来先服务]
F2[简单粗暴]
F3[大任务会饿死小任务]
F4[生产环境不推荐]
end
subgraph Capacity["Capacity Scheduler"]
C1[容量调度器]
C2[多队列,每个队列有容量保证]
C3[队列内FIFO]
C4[Apache默认调度器]
end
subgraph Fair["Fair Scheduler"]
FA1[公平调度器]
FA2[动态公平分配资源]
FA3[支持抢占]
FA4[CDH默认调度器]
end
end
style FIFO fill:#ff6b6b
style Capacity fill:#4ecdc4
style Fair fill:#ffe66d
3.2 FIFO Scheduler:简单但不实用
gantt
title FIFO调度示意图
dateFormat X
axisFormat %s
section 任务执行
大任务Job1 (需要80%资源) :a1, 0, 100
小任务Job2 (需要10%资源) :a2, after a1, 10
小任务Job3 (需要10%资源) :a3, after a2, 10
问题:Job1跑了100秒,Job2和Job3只能干等着。即使它们只需要10%的资源,也得排队。
这就像食堂只有一个窗口,前面有人买100个包子,你买1个也得等他买完。
3.3 Capacity Scheduler:容量保证
graph TB
subgraph Capacity调度器["📊 Capacity Scheduler"]
Root[Root Queue<br/>100%]
Root --> QA[Queue A<br/>40%容量<br/>数据团队]
Root --> QB[Queue B<br/>60%容量<br/>算法团队]
QA --> QA1[子队列A1<br/>50% of A]
QA --> QA2[子队列A2<br/>50% of A]
QB --> QB1[子队列B1<br/>70% of B]
QB --> QB2[子队列B2<br/>30% of B]
end
subgraph 特性["💡 特性"]
T1[每个队列有最小容量保证]
T2[空闲资源可以借给其他队列]
T3[支持队列层级结构]
T4[可以限制用户/应用的资源使用]
end
style Root fill:#ff6b6b
style QA fill:#4ecdc4
style QB fill:#ffe66d
容量调度器的配置示例:
<!-- capacity-scheduler.xml -->
<configuration>
<!-- 定义队列 -->
<property>
<name>yarn.scheduler.capacity.root.queues</name>
<value>data,algo</value>
</property>
<!-- data队列容量40% -->
<property>
<name>yarn.scheduler.capacity.root.data.capacity</name>
<value>40</value>
</property>
<!-- algo队列容量60% -->
<property>
<name>yarn.scheduler.capacity.root.algo.capacity</name>
<value>60</value>
</property>
<!-- data队列最大可使用70%(可以借用空闲资源) -->
<property>
<name>yarn.scheduler.capacity.root.data.maximum-capacity</name>
<value>70</value>
</property>
</configuration>
3.4 Fair Scheduler:公平分配
graph TB
subgraph Fair调度器["⚖️ Fair Scheduler"]
subgraph 时刻1["时刻T1:只有Job1"]
T1J1[Job1: 100%资源]
end
subgraph 时刻2["时刻T2:Job2加入"]
T2J1[Job1: 50%资源]
T2J2[Job2: 50%资源]
end
subgraph 时刻3["时刻T3:Job3加入"]
T3J1[Job1: 33%资源]
T3J2[Job2: 33%资源]
T3J3[Job3: 33%资源]
end
subgraph 时刻4["时刻T4:Job1完成"]
T4J2[Job2: 50%资源]
T4J3[Job3: 50%资源]
end
end
时刻1 --> 时刻2 --> 时刻3 --> 时刻4
style T1J1 fill:#ff6b6b
style T2J1 fill:#ff6b6b
style T2J2 fill:#4ecdc4
style T3J1 fill:#ff6b6b
style T3J2 fill:#4ecdc4
style T3J3 fill:#ffe66d
Fair Scheduler的核心思想:在任何时刻,所有运行的应用平均分配资源。
支持抢占:如果某个应用占用资源超过其公平份额,调度器可以"抢回"一部分资源给其他应用。
3.5 调度器选择建议
graph TB
subgraph 选择指南["🤔 如何选择调度器"]
Q1{多少团队共用集群?}
Q1 --> |"单团队"|A1[FIFO或Capacity]
Q1 --> |"多团队"|Q2{需要资源抢占?}
Q2 --> |"不需要"|A2[Capacity Scheduler<br/>配置多个队列]
Q2 --> |"需要"|A3[Fair Scheduler<br/>公平+抢占]
Q3{使用什么发行版?}
Q3 --> |"Apache原生"|A4[默认Capacity]
Q3 --> |"CDH/HDP"|A5[默认Fair]
end
style A2 fill:#4ecdc4
style A3 fill:#ffe66d
四、YARN高可用(HA)
和HDFS一样,ResourceManager也有单点故障问题。YARN HA的解决方案:
graph TB
subgraph YARN_HA["🔄 YARN HA架构"]
subgraph Active["主节点"]
ARM[Active RM<br/>正在服务]
end
subgraph Standby["备节点"]
SRM[Standby RM<br/>热备待命]
end
subgraph ZK["ZooKeeper集群"]
ZK1[ZK1]
ZK2[ZK2]
ZK3[ZK3]
end
subgraph StateStore["状态存储"]
SS[ZK / HDFS / LevelDB<br/>存储应用状态]
end
subgraph NMs["NodeManager集群"]
NM1[NM1]
NM2[NM2]
NM3[NM3]
end
end
ARM --> ZK1
SRM --> ZK1
ARM --> SS
SRM --> SS
ARM --> NM1
ARM --> NM2
ARM --> NM3
style ARM fill:#4ecdc4,stroke:#333,stroke-width:2px
style SRM fill:#ffe66d
故障切换流程:
sequenceDiagram
participant ARM as Active RM
participant ZK as ZooKeeper
participant SRM as Standby RM
participant SS as StateStore
participant NM as NodeManagers
Note over ARM: Active RM挂了💀
ARM->>ZK: 心跳停止
ZK->>ZK: 检测到Active失联
ZK->>SRM: 通知:你来当Active
SRM->>SS: 恢复应用状态
SRM->>SRM: 切换为Active状态
SRM->>NM: 接管所有NodeManager
Note over SRM: 服务恢复✅
五、YARN常用命令
5.1 应用管理命令
# 查看所有应用
yarn application -list
# 查看指定状态的应用
yarn application -list -appStates RUNNING
yarn application -list -appStates FINISHED
yarn application -list -appStates KILLED
# 杀死应用
yarn application -kill application_1234567890123_0001
# 查看应用状态
yarn application -status application_1234567890123_0001
# 查看应用日志
yarn logs -applicationId application_1234567890123_0001
yarn logs -applicationId application_1234567890123_0001 -containerId container_123
5.2 集群管理命令
# 查看集群状态
yarn cluster -status
# 查看节点列表
yarn node -list
yarn node -list -all
yarn node -list -states RUNNING
# 查看节点详情
yarn node -status node1:8041
# 查看队列信息
yarn queue -status default
5.3 资源管理命令
# 刷新队列配置(不重启生效)
yarn rmadmin -refreshQueues
# 刷新节点
yarn rmadmin -refreshNodes
# 查看ResourceManager状态(HA模式)
yarn rmadmin -getServiceState rm1
yarn rmadmin -getServiceState rm2
# 手动切换Active RM
yarn rmadmin -transitionToActive rm2 --forcemanual
六、Hadoop生态圈:大象的朋友们
终于到了最精彩的部分——Hadoop生态圈。Hadoop不是一个人在战斗,它有一群强大的小伙伴。
6.1 生态圈全景图
graph TB
subgraph 生态圈["🦁 Hadoop生态圈全景图"]
subgraph 数据采集["📥 数据采集层"]
Flume[Flume<br/>日志采集]
Sqoop[Sqoop<br/>关系数据库导入导出]
Kafka[Kafka<br/>消息队列]
NiFi[NiFi<br/>数据流]
end
subgraph 存储层["💾 存储层"]
HDFS[HDFS<br/>分布式文件系统]
HBase[HBase<br/>列式NoSQL数据库]
Kudu[Kudu<br/>列式存储引擎]
end
subgraph 计算层["⚡ 计算层"]
MR[MapReduce<br/>批处理]
Spark[Spark<br/>内存计算]
Flink[Flink<br/>流批一体]
Tez[Tez<br/>DAG计算]
end
subgraph 查询层["🔍 查询层"]
Hive[Hive<br/>SQL on Hadoop]
Presto[Presto<br/>交互式查询]
Impala[Impala<br/>MPP查询引擎]
Pig[Pig<br/>数据流脚本]
end
subgraph 资源管理["🎛️ 资源管理"]
YARN[YARN<br/>资源调度]
Mesos[Mesos<br/>通用资源管理]
K8s[Kubernetes<br/>容器编排]
end
subgraph 协调服务["🔧 协调服务"]
ZK[ZooKeeper<br/>分布式协调]
Oozie[Oozie<br/>工作流调度]
Airflow[Airflow<br/>任务编排]
end
end
数据采集 --> 存储层
存储层 --> 计算层
计算层 --> 查询层
资源管理 --> 计算层
协调服务 --> 资源管理
style HDFS fill:#4ecdc4
style YARN fill:#4ecdc4
style Hive fill:#ffe66d
style Spark fill:#ff6b6b
style Flink fill:#ff6b6b
style HBase fill:#9b59b6
6.2 核心组件详解
Hive:让你用SQL操作大数据
graph TB
subgraph Hive["🐝 Hive架构"]
Client[用户] --> |"SQL"|HiveQL[HiveQL]
HiveQL --> Driver[Driver<br/>编译SQL]
Driver --> Metastore[Metastore<br/>元数据存储]
Driver --> Execution[执行引擎]
Execution --> |"转换成"|MR[MapReduce]
Execution --> |"或"|Spark2[Spark]
Execution --> |"或"|Tez2[Tez]
MR --> HDFS2[HDFS]
end
subgraph 特点["💡 特点"]
T1[SQL on Hadoop]
T2[适合离线批处理]
T3[延迟高,不适合交互式查询]
T4[数据仓库首选]
end
style Hive fill:#ffe66d
Hive示例:
-- 创建表
CREATE TABLE user_behavior (
user_id STRING,
action STRING,
timestamp BIGINT
)
PARTITIONED BY (dt STRING)
STORED AS PARQUET;
-- 查询(会被转换成MapReduce/Spark任务)
SELECT action, COUNT(*) as cnt
FROM user_behavior
WHERE dt = '2024-01-01'
GROUP BY action
ORDER BY cnt DESC
LIMIT 10;
HBase:海量数据的实时读写
graph TB
subgraph HBase["🗄️ HBase架构"]
Client2[客户端] --> ZK2[ZooKeeper<br/>协调服务]
ZK2 --> HMaster[HMaster<br/>管理RegionServer]
HMaster --> RS1[RegionServer1]
HMaster --> RS2[RegionServer2]
HMaster --> RS3[RegionServer3]
RS1 --> HDFS3[HDFS]
RS2 --> HDFS3
RS3 --> HDFS3
end
subgraph 特点2["💡 特点"]
H1[列式存储NoSQL]
H2[支持随机读写]
H3[毫秒级延迟]
H4[适合稀疏数据]
end
style HBase fill:#9b59b6
HBase vs HDFS vs 传统数据库:
| 特性 | HDFS | HBase | MySQL |
|---|
| 数据模型 | 文件 | 列族 | 表/行 |
| 读写模式 | 一次写多次读 | 随机读写 | 随机读写 |
| 延迟 | 高(秒级) | 低(毫秒级) | 低(毫秒级) |
| 数据量 | PB级 | PB级 | TB级 |
| 适用场景 | 批处理 | 实时查询 | OLTP |
Spark:内存计算的王者
graph TB
subgraph Spark["⚡ Spark架构"]
subgraph Driver["Driver Program"]
SC[SparkContext]
end
subgraph Cluster["Cluster Manager"]
CM[YARN / Standalone / Mesos / K8s]
end
subgraph Workers["Worker Nodes"]
E1[Executor1]
E2[Executor2]
E3[Executor3]
E1 --> T1[Task]
E1 --> T2[Task]
E2 --> T3[Task]
E2 --> T4[Task]
E3 --> T5[Task]
E3 --> T6[Task]
end
SC --> CM
CM --> E1
CM --> E2
CM --> E3
end
subgraph Spark生态["Spark生态"]
Core[Spark Core<br/>RDD]
SQL[Spark SQL<br/>结构化数据]
Streaming[Spark Streaming<br/>流处理]
MLlib[MLlib<br/>机器学习]
GraphX[GraphX<br/>图计算]
end
style Spark fill:#ff6b6b
Spark vs MapReduce:
graph LR
subgraph MR处理["MapReduce处理流程"]
MR1[读HDFS] --> MR2[Map]
MR2 --> MR3[写磁盘]
MR3 --> MR4[读磁盘]
MR4 --> MR5[Reduce]
MR5 --> MR6[写HDFS]
MR6 --> MR7[读HDFS]
MR7 --> MR8[下一个Job...]
end
subgraph Spark处理["Spark处理流程"]
S1[读HDFS] --> S2[Transform1]
S2 --> |"内存"|S3[Transform2]
S3 --> |"内存"|S4[Transform3]
S4 --> |"内存"|S5[Action]
S5 --> S6[写HDFS]
end
style MR3 fill:#ff6b6b
style MR4 fill:#ff6b6b
style MR6 fill:#ff6b6b
style MR7 fill:#ff6b6b
style S2 fill:#4ecdc4
style S3 fill:#4ecdc4
style S4 fill:#4ecdc4
结论:Spark通过内存计算,避免了MapReduce频繁的磁盘IO,速度提升10-100倍。
Flink:流批一体的未来
graph TB
subgraph Flink["🌊 Flink架构"]
subgraph FM["Flink Master"]
JM[JobManager<br/>作业管理]
RM2[ResourceManager]
Dispatcher[Dispatcher]
end
subgraph TMs["Task Managers"]
TM1[TaskManager1]
TM2[TaskManager2]
TM3[TaskManager3]
end
JM --> TM1
JM --> TM2
JM --> TM3
end
subgraph 特点3["💡 Flink特点"]
F1[真正的流处理<br/>事件驱动]
F2[精确一次语义<br/>Exactly-Once]
F3[低延迟<br/>毫秒级]
F4[流批一体<br/>统一API]
end
style Flink fill:#ff6b6b
流处理框架对比:
| 框架 | 处理模型 | 延迟 | 精确一次 | 适用场景 |
|---|
| Spark Streaming | 微批处理 | 秒级 | ✅ | 准实时 |
| Flink | 真正流处理 | 毫秒级 | ✅ | 实时 |
| Storm | 流处理 | 毫秒级 | ❌(需额外处理) | 简单实时 |
| Kafka Streams | 流处理 | 毫秒级 | ✅ | 轻量级 |
6.3 技术选型指南
graph TB
subgraph 选型指南["🤔 技术选型决策树"]
Q1{数据处理需求?}
Q1 --> |"批处理"|Q2{数据规模?}
Q2 --> |"TB级以下"|A1[Spark]
Q2 --> |"PB级"|A2[Spark/MapReduce]
Q1 --> |"实时处理"|Q3{延迟要求?}
Q3 --> |"秒级"|A3[Spark Streaming]
Q3 --> |"毫秒级"|A4[Flink]
Q1 --> |"交互式查询"|Q4{数据存储?}
Q4 --> |"HDFS"|A5[Presto/Impala/SparkSQL]
Q4 --> |"HBase"|A6[Phoenix]
Q1 --> |"随机读写"|A7[HBase]
Q1 --> |"数据仓库"|A8[Hive + Spark]
end
style A1 fill:#ff6b6b
style A4 fill:#ff6b6b
style A8 fill:#ffe66d
七、一个完整的大数据架构案例
让我们看看一个真实的电商公司是怎么搭建大数据平台的:
graph TB
subgraph 数据源["📱 数据源"]
App[App埋点]
Web[Web日志]
DB[(MySQL<br/>业务数据库)]
Third[第三方数据]
end
subgraph 采集层["📥 数据采集"]
Flume2[Flume<br/>日志采集]
Kafka2[Kafka<br/>消息队列]
Sqoop2[Sqoop<br/>数据库同步]
Canal[Canal<br/>Binlog采集]
end
subgraph 存储层["💾 数据存储"]
subgraph 数据湖["数据湖"]
HDFS4[HDFS<br/>原始数据]
end
subgraph 数据仓库["数据仓库"]
ODS[ODS层<br/>原始数据]
DWD[DWD层<br/>明细数据]
DWS[DWS层<br/>汇总数据]
ADS[ADS层<br/>应用数据]
end
HBase2[HBase<br/>实时查询]
ES[Elasticsearch<br/>搜索/日志]
Redis[(Redis<br/>缓存)]
end
subgraph 计算层["⚡ 数据计算"]
Spark3[Spark<br/>离线计算]
Flink2[Flink<br/>实时计算]
Hive2[Hive<br/>数仓查询]
end
subgraph 服务层["🖥️ 数据服务"]
API[数据API]
BI[BI报表]
ML[机器学习平台]
Search[搜索服务]
end
subgraph 调度监控["🔧 调度&监控"]
Airflow2[Airflow<br/>任务调度]
Monitor[监控告警]
end
App --> Flume2
Web --> Flume2
DB --> Canal
DB --> Sqoop2
Third --> Kafka2
Flume2 --> Kafka2
Canal --> Kafka2
Sqoop2 --> HDFS4
Kafka2 --> HDFS4
Kafka2 --> Flink2
Kafka2 --> HBase2
HDFS4 --> ODS
ODS --> DWD
DWD --> DWS
DWS --> ADS
Spark3 --> 数据仓库
Hive2 --> 数据仓库
Flink2 --> HBase2
Flink2 --> ES
Flink2 --> Redis
ADS --> API
ADS --> BI
HBase2 --> API
ES --> Search
Spark3 --> ML
Airflow2 --> Spark3
Airflow2 --> Hive2
style HDFS4 fill:#4ecdc4
style Spark3 fill:#ff6b6b
style Flink2 fill:#ff6b6b
style Hive2 fill:#ffe66d
架构说明
| 层次 | 组件 | 作用 |
|---|
| 采集层 | Flume + Kafka + Canal | 收集各种数据源的数据 |
| 存储层 | HDFS + HBase + ES | 存储不同类型的数据 |
| 计算层 | Spark + Flink + Hive | 批处理和实时处理 |
| 服务层 | API + BI | 对外提供数据服务 |
| 调度层 | Airflow | 管理任务依赖和调度 |
八、Hadoop的未来:云原生时代
随着云计算的发展,Hadoop也在不断进化:
timeline
title Hadoop的进化之路
传统时代 : 自建机房
: 物理服务器
: 运维成本高
云化时代 : 云上部署Hadoop
: EMR/HDInsight/Dataproc
: 弹性扩缩容
存算分离时代 : 计算和存储分离
: 对象存储替代HDFS
: S3/OSS/GCS
云原生时代 : Spark on K8s
: Flink on K8s
: Serverless大数据
: 按需付费
湖仓一体时代 : Delta Lake
: Apache Iceberg
: Apache Hudi
: 统一批流存储
现代数据架构趋势
graph TB
subgraph 传统架构["😰 传统Lambda架构"]
B1[批处理层] --> B2[Hadoop/Spark]
S1[流处理层] --> S2[Storm/Flink]
Serve1[服务层] --> B2
Serve1 --> S2
Note1[维护两套代码<br/>数据一致性难保证]
end
subgraph 现代架构["✅ 现代Lakehouse架构"]
DL[Data Lakehouse<br/>Delta Lake/Iceberg/Hudi]
DL --> Batch[批处理]
DL --> Stream[流处理]
DL --> ML2[机器学习]
DL --> BI2[BI分析]
Note2[统一存储<br/>流批一体<br/>ACID事务]
end
style Note1 fill:#ff6b6b
style Note2 fill:#4ecdc4
九、全系列总结
三篇文章,我们走完了Hadoop从入门到......还没放弃的旅程。让我们做一个全面的回顾:
mindmap
root((Hadoop从入门到放弃))
第一篇:HDFS
分布式文件系统
NameNode/DataNode
Block/副本机制
读写流程
HA/Federation
第二篇:MapReduce
分而治之思想
Map/Shuffle/Reduce
Combiner/Partitioner
数据倾斜
性能调优
第三篇:YARN+生态
资源管理
RM/NM/AM/Container
调度器
Hive/HBase/Spark/Flink
完整架构案例
学习路线建议
graph LR
subgraph 学习路线["📚 大数据学习路线"]
L1[Linux基础] --> L2[Java/Scala/Python]
L2 --> L3[Hadoop基础<br/>HDFS+MR+YARN]
L3 --> L4[Hive数仓]
L4 --> L5[Spark]
L5 --> L6{方向选择}
L6 --> |"离线方向"|L7[数仓建模<br/>Hive优化]
L6 --> |"实时方向"|L8[Flink<br/>Kafka]
L6 --> |"平台方向"|L9[调度系统<br/>数据治理]
L7 --> L10[数据架构师]
L8 --> L10
L9 --> L10
end
style L3 fill:#4ecdc4
style L5 fill:#ff6b6b
style L10 fill:#ffe66d
十、写在最后
写到这里,Hadoop系列终于完结了。
回想起我刚开始学Hadoop的时候,面对一堆概念完全懵逼:NameNode、DataNode、JobTracker、TaskTracker、ResourceManager、NodeManager、ApplicationMaster......每个都是Manager,每个都是Node,到底谁管谁?
后来我发现,其实大数据技术的核心思想就那么几个:
- 分而治之:大任务拆小任务
- 数据冗余:用副本保证可靠性
- 移动计算:计算向数据靠拢
- 分层架构:存储、计算、调度分离
掌握了这些思想,再去学任何大数据组件都会轻松很多。
最后的最后,送给大家几句话:
"不要被技术的复杂性吓倒,所有复杂的系统都是由简单的模块组成的。"
"Hadoop可能会过时,但分布式计算的思想永远不会。"
"学习大数据最好的方式是:先跑起来,再深入原理。"
如果你真的认真看完了这三篇文章,恭喜你——你已经超过了80%的"大数据工程师"。
接下来,去动手搭个集群,跑几个任务,踩几个坑,你就真的入门了。
感谢阅读,我们下个系列见!🐘🐘🐘
本文作者:一个在凌晨三点调过YARN配置的程序员
最惨经历:调了一晚上参数,第二天发现是网线没插好
系列完结,撒花🎉
附录A:Hadoop生态圈速查表
| 组件 | 类型 | 一句话描述 |
|---|
| HDFS | 存储 | 分布式文件系统,存海量数据 |
| YARN | 调度 | 资源管理,给各种应用分配资源 |
| MapReduce | 计算 | 批处理计算框架,慢但稳 |
| Hive | 查询 | SQL on Hadoop,数仓首选 |
| HBase | 存储 | 列式NoSQL,支持随机读写 |
| Spark | 计算 | 内存计算,比MR快10-100倍 |
| Flink | 计算 | 流批一体,真正的实时 |
| Kafka | 消息 | 消息队列,数据管道 |
| Flume | 采集 | 日志采集工具 |
| Sqoop | 导入导出 | 关系数据库与Hadoop之间搬数据 |
| ZooKeeper | 协调 | 分布式协调服务,选主、配置管理 |
| Oozie | 调度 | 工作流调度,管理任务依赖 |
| Presto | 查询 | 交互式查询,秒级响应 |
| Impala | 查询 | MPP查询引擎,类似Presto |
附录B:面试高频题合集
YARN相关
YARN的架构是什么?各组件的作用?
RM负责全局资源管理,NM管理单节点资源,AM管理单个应用,Container是资源抽象。
YARN的作业提交流程?
客户端提交 → RM分配Container启动AM → AM向RM申请资源 → AM通知NM启动Container → 任务执行 → 完成释放资源
YARN有哪些调度器?区别是什么?
FIFO(先进先出)、Capacity(容量保证)、Fair(公平分配)。生产环境一般用Capacity或Fair。
Container和虚拟机/Docker的区别?
Container是YARN的资源抽象,不是真正的隔离容器。它只是逻辑上的资源限制(CPU、内存),不像Docker有文件系统隔离。
生态圈相关
Hive和传统数据库的区别?
Hive是数据仓库工具,基于HDFS,适合离线批处理,延迟高;传统数据库适合OLTP,低延迟。
HBase的rowkey设计原则?
唯一性、散列性(避免热点)、长度适中(10-100字节)、业务相关性。
Spark和MapReduce的区别?
Spark基于内存计算,支持丰富算子,适合迭代计算;MR中间结果写磁盘,只有Map和Reduce两个算子。
Flink和Spark Streaming的区别?
Flink是真正的流处理(事件驱动),Spark Streaming是微批处理。Flink延迟更低(毫秒级vs秒级)。
评论
还没有评论,来说点什么吧。