搜 索

大数据之Hadoop从入门到放弃之hadoop的小伙伴们

  • 21阅读
  • 2023年01月14日
  • 0评论
首页 / AI/大数据 / 正文

前言:一个关于"抢资源"的故事

在讲YARN之前,让我先讲一个真实的故事。

那是Hadoop 1.x的时代,我们公司有一个50台机器的Hadoop集群。某天,数据组的小王提交了一个MapReduce任务,跑全年的用户行为分析;与此同时,算法组的小李也提交了一个任务,训练推荐模型。

然后,整个集群就陷入了混乱——两个任务疯狂抢资源,互相等待,谁也跑不完。

更惨的是,运维组的老张想跑一个Spark任务做实时监控,但是——对不起,Hadoop 1.x只支持MapReduce,不支持Spark

老张当场表演了一个原地裂开。

"如果有一个统一的资源管理系统,能管理所有类型的计算任务,该多好啊……"

于是,YARN诞生了。

本篇是Hadoop系列的最后一篇,我们将学习:

  1. YARN:Hadoop的资源管理系统
  2. Hadoop生态圈:大象的朋友们

让我们开始最后的冲刺!


一、从Hadoop 1.x到2.x:架构的进化

1.1 Hadoop 1.x的架构问题

graph TB subgraph Hadoop1["😰 Hadoop 1.x 架构"] subgraph MRv1["MapReduce v1"] JT[JobTracker
作业调度 + 资源管理
一个人干两份活] 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单点故障
挂了全完蛋] P2[2. JobTracker负担太重
既管资源又管调度] P3[3. 只支持MapReduce
想跑Spark?没门] P4[4. 资源利用率低
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
全局资源管理] 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
资源管理者
大管家] end subgraph RM内部["ResourceManager内部"] Scheduler[Scheduler
调度器
只负责分配资源] ASM[ApplicationsManager
应用管理器
管理所有应用] end subgraph 节点["每个节点"] NM1[NodeManager
节点管理器
管理单个节点资源] NM2[NodeManager] NM3[NodeManager] end subgraph 应用["每个应用"] AM1[ApplicationMaster
应用主管
管理单个应用] C1[Container
资源容器] 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
资源抽象] 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-7RM找一台机器启动AM,AM开始规划任务HR给你分配一个项目经理
8-11AM向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
100%] Root --> QA[Queue A
40%容量
数据团队] Root --> QB[Queue B
60%容量
算法团队] QA --> QA1[子队列A1
50% of A] QA --> QA2[子队列A2
50% of A] QB --> QB1[子队列B1
70% of B] QB --> QB2[子队列B2
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
配置多个队列] Q2 --> |"需要"|A3[Fair Scheduler
公平+抢占] 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
正在服务] end subgraph Standby["备节点"] SRM[Standby RM
热备待命] end subgraph ZK["ZooKeeper集群"] ZK1[ZK1] ZK2[ZK2] ZK3[ZK3] end subgraph StateStore["状态存储"] SS[ZK / HDFS / LevelDB
存储应用状态] 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
日志采集] Sqoop[Sqoop
关系数据库导入导出] Kafka[Kafka
消息队列] NiFi[NiFi
数据流] end subgraph 存储层["💾 存储层"] HDFS[HDFS
分布式文件系统] HBase[HBase
列式NoSQL数据库] Kudu[Kudu
列式存储引擎] end subgraph 计算层["⚡ 计算层"] MR[MapReduce
批处理] Spark[Spark
内存计算] Flink[Flink
流批一体] Tez[Tez
DAG计算] end subgraph 查询层["🔍 查询层"] Hive[Hive
SQL on Hadoop] Presto[Presto
交互式查询] Impala[Impala
MPP查询引擎] Pig[Pig
数据流脚本] end subgraph 资源管理["🎛️ 资源管理"] YARN[YARN
资源调度] Mesos[Mesos
通用资源管理] K8s[Kubernetes
容器编排] end subgraph 协调服务["🔧 协调服务"] ZK[ZooKeeper
分布式协调] Oozie[Oozie
工作流调度] Airflow[Airflow
任务编排] 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
编译SQL] Driver --> Metastore[Metastore
元数据存储] 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
协调服务] ZK2 --> HMaster[HMaster
管理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 传统数据库

特性HDFSHBaseMySQL
数据模型文件列族表/行
读写模式一次写多次读随机读写随机读写
延迟高(秒级)低(毫秒级)低(毫秒级)
数据量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
RDD] SQL[Spark SQL
结构化数据] Streaming[Spark Streaming
流处理] MLlib[MLlib
机器学习] GraphX[GraphX
图计算] 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
作业管理] 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[真正的流处理
事件驱动] F2[精确一次语义
Exactly-Once] F3[低延迟
毫秒级] F4[流批一体
统一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
业务数据库)] Third[第三方数据] end subgraph 采集层["📥 数据采集"] Flume2[Flume
日志采集] Kafka2[Kafka
消息队列] Sqoop2[Sqoop
数据库同步] Canal[Canal
Binlog采集] end subgraph 存储层["💾 数据存储"] subgraph 数据湖["数据湖"] HDFS4[HDFS
原始数据] end subgraph 数据仓库["数据仓库"] ODS[ODS层
原始数据] DWD[DWD层
明细数据] DWS[DWS层
汇总数据] ADS[ADS层
应用数据] end HBase2[HBase
实时查询] ES[Elasticsearch
搜索/日志] Redis[(Redis
缓存)] end subgraph 计算层["⚡ 数据计算"] Spark3[Spark
离线计算] Flink2[Flink
实时计算] Hive2[Hive
数仓查询] end subgraph 服务层["🖥️ 数据服务"] API[数据API] BI[BI报表] ML[机器学习平台] Search[搜索服务] end subgraph 调度监控["🔧 调度&监控"] Airflow2[Airflow
任务调度] 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[维护两套代码
数据一致性难保证] end subgraph 现代架构["✅ 现代Lakehouse架构"] DL[Data Lakehouse
Delta Lake/Iceberg/Hudi] DL --> Batch[批处理] DL --> Stream[流处理] DL --> ML2[机器学习] DL --> BI2[BI分析] Note2[统一存储
流批一体
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基础
HDFS+MR+YARN] L3 --> L4[Hive数仓] L4 --> L5[Spark] L5 --> L6{方向选择} L6 --> |"离线方向"|L7[数仓建模
Hive优化] L6 --> |"实时方向"|L8[Flink
Kafka] L6 --> |"平台方向"|L9[调度系统
数据治理] 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,到底谁管谁?

后来我发现,其实大数据技术的核心思想就那么几个:

  1. 分而治之:大任务拆小任务
  2. 数据冗余:用副本保证可靠性
  3. 移动计算:计算向数据靠拢
  4. 分层架构:存储、计算、调度分离

掌握了这些思想,再去学任何大数据组件都会轻松很多。

最后的最后,送给大家几句话:

"不要被技术的复杂性吓倒,所有复杂的系统都是由简单的模块组成的。"

"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相关

  1. YARN的架构是什么?各组件的作用?

    RM负责全局资源管理,NM管理单节点资源,AM管理单个应用,Container是资源抽象。
  2. YARN的作业提交流程?

    客户端提交 → RM分配Container启动AM → AM向RM申请资源 → AM通知NM启动Container → 任务执行 → 完成释放资源
  3. YARN有哪些调度器?区别是什么?

    FIFO(先进先出)、Capacity(容量保证)、Fair(公平分配)。生产环境一般用Capacity或Fair。
  4. Container和虚拟机/Docker的区别?

    Container是YARN的资源抽象,不是真正的隔离容器。它只是逻辑上的资源限制(CPU、内存),不像Docker有文件系统隔离。

生态圈相关

  1. Hive和传统数据库的区别?

    Hive是数据仓库工具,基于HDFS,适合离线批处理,延迟高;传统数据库适合OLTP,低延迟。
  2. HBase的rowkey设计原则?

    唯一性、散列性(避免热点)、长度适中(10-100字节)、业务相关性。
  3. Spark和MapReduce的区别?

    Spark基于内存计算,支持丰富算子,适合迭代计算;MR中间结果写磁盘,只有Map和Reduce两个算子。
  4. Flink和Spark Streaming的区别?

    Flink是真正的流处理(事件驱动),Spark Streaming是微批处理。Flink延迟更低(毫秒级vs秒级)。
评论区
暂无评论
avatar