首页 / 资讯中心 / 文章详情

Hadoop核心组件详解:HDFS、MapReduce与YARN实战指南

Hadoop核心组件详解:HDFS、MapReduce与YARN实战指南 ★ FEATURED ARTICLE
1. 先搞清楚Hadoop究竟是软件、框架还是一种“思路”我第一次系统接触Hadoop是因为一个再朴素不过的需求服务器每天产生几十GB的访问日志单机数据库已经快撑不住业务方又要按天、按渠道、按用户维度出汇总报表。当时我对“大数据”的理解还停留在PPT上直到自己把集群搭起来、跑出第一份统计结果才终于明白了那个最基础的问题——什么是Hadoop。用一句话说Hadoop是一套把大量普通机器组织起来协同存储和处理海量数据的开源基础软件。它通常由三个核心部分组成分布式文件系统HDFS负责把文件拆成数据块分散存到多台机器上资源调度框架YARN负责统筹集群里每台机器上的CPU和内存计算模型MapReduce负责把一个大任务拆成很多小任务并行执行最后再把结果合并。三部分配合起来产生的效果是你可以用一堆廉价服务器去处理单机根本存不下、算不动的数据而且需要扩容时直接加机器就行不用把现有架构推倒重来。理解Hadoop最关键的一点其实是它背后的设计思路数据不搬家计算去找数据。传统关系型数据库处理数据是把数据集中在某台机器上由那台机器来算数据量如果大到一台机器装不下这条路就走死了。Hadoop反过来想——既然数据量太大搬不动那就不搬把数据打散放在所有机器上谁存了哪份数据谁就来算自己手里那份最后统一汇总。这个思路看着简单却奠定了整个大数据生态的地基。那它和普通数据库的区别在哪里呢最常见的误解是“Hadoop就是个大号数据库”。其实Hadoop并不适合做在线事务处理它不是用来支撑“用户点一下按钮立刻返回一条记录”这种场景的。它的主战场是批量分析和数据加工把几十TB甚至PB级的历史数据一次性扫一遍跑几小时甚至更长时间产出报表、训练数据、特征文件这类结果。说得更直白一点关系型数据库像超市的收银台讲究的是每笔交易快速完成Hadoop更像一个大型自动化仓库讲究的是一次性吞吐能力吞吐量和扩展性才是它存在的意义。所以这篇内容适合谁看呢一种是刚开始接触分布式、被各种概念绕晕的新人一种是只会写SQL和单机脚本、想搞明白“数据量大了之后到底该干嘛”的工程师还有一种是准备做技术选型想知道当前场景到底要不要上Hadoop的架构师。下面我会把HDFS、MapReduce、YARN三个核心组件一个一个拆开讲顺带附上一套能在你自己电脑上跑起来的最小实操流程最后把实际使用中最容易踩的坑集中列一遍。2. 为什么要折腾出Hadoop老办法到底卡在哪里要真正理解一个技术最好先知道它出生前大家在用什么、为什么不够用。在Hadoop出现之前处理数据的常规思路是“先把数据集中起来然后找一台足够大的机器去算”。这看起来没毛病但数据量一旦跨过某个临界点三个问题会同时冒出来。第一个问题是存储。单机硬盘容量再怎么涨也有物理上限而且大容量磁盘价格不便宜宕机了数据恢复也麻烦。更现实的场景是很多公司的数据天生就是分布式的——不同业务线的日志、不同地区的订单、不同设备上报的监控数据本来就落在不同机器上。把它们全部搬到一个机房、一台机器先不说带宽成本光是拷贝和等待的时间就让人绝望。第二个问题是计算。就算数据勉强集中到了同一台机器上单机的CPU和内存也扛不住大规模计算。举个例子对一亿行记录做统计单机可能要把数据分块循环处理一跑就是几小时加了索引、做了优化也只能缓解解决不了本质问题。这时候有种思路叫“向上扩展”也就是换更大的机器但大机器不仅贵而且你会碰到新的瓶颈——内存通道、磁盘IO、系统软件的可扩展性都未必跟得上。第三个问题也是最容易被忽略的机器故障。当你手头只有一台机器时它挂了就是单点故障但当你手头有几十台机器时每天都会有某台机器莫名其妙的出问题这是一条统计规律不是运气问题。如果你的计算任务是分布式的却没有容错机制那任何一台机器罢工都可能导致整个任务失败甚至结果错误。Hadoop解决这三个问题的方式看起来非常“笨”但非常有效存储上它把文件切分成固定大小的数据块默认128MB一块多副本保存就算某台机器上的硬盘坏了数据还能从其他机器副本里恢复计算上它把一个任务拆分成很多并行的小任务每台机器只处理自己本地能访问到的数据做完一部分再聚合调度上由YARN统一管理集群资源任务失败会自动重跑不需要人工介入。这里面最值得展开的是“数据本地性”这个概念。分布式系统里网络传输是最贵的资源比CPU运算贵得多。如果任务和数据不在同一台机器上每次计算都要先从远端把数据拉过来集群规模一大网络就变成了瓶颈。Hadoop的设计是让调度器优先把计算任务分给“数据所在的那台机器”去执行实在不行再退而求其次放到同一机架的其他机器上。这个优化听着不起眼但在实际生产里它往往能决定整个集群的吞吐量也是Hadoop后续各种计算框架都继承的设计原则。所以你看Hadoop不是为了炫技造出来的它是被海量数据的存储、计算和容错需求一步步逼出来的产物。理解了它的动机再看它的三个核心组件基本上就能顺着往下捋了。3. 核心组件逐个拆HDFS、MapReduce、YARN各自管什么3.1 HDFS把一台大硬盘拆成很多台小硬盘还要对外伪装成“一台”HDFS分布式文件系统是Hadoop的存储底座。它的工作方式可以类比成拆硬盘一份200GB的大文件被切成很多个128MB的块每块复制三份散布到集群不同的机器上。这样从用户视角看它还是一份完整的文件可以像操作普通文件一样读写但从物理层面看这份文件已经碎成很多小块散布在整个机房了。HDFS里有两个核心角色NameNode和DataNode。NameNode是元数据管家只记录“哪个文件由哪些块组成、每个块存在哪些机器上”不存实际数据DataNode才是真正存数据块的苦力。客户端要读文件时先问NameNode要一份块清单然后直接去对应的DataNode拉数据要写文件时也是先问NameNode申请路径和块位置再把数据写进DataNode最后传回确认。这里有两个参数特别值得新人记住。一个是块大小默认128MB。块设得大是为了减少元数据条数和磁盘寻道次数但这不代表你所有文件都该凑够128MB一个只有几十KB的小文件也会占一条元数据这个问题后面我会在坑里单独讲。另一个是副本系数默认3。三副本是“两副本防数据损坏、一副本防机器宕机”的经典组合但也不是越多越好副本越多占的磁盘成本越高像数据仓库里的临时表完全可以把副本降到1反正坏了还能重跑生成。HDFS还有一个非常实用的特性叫“流式访问”它更擅长顺序读大文件而不是随机读写。很多人一开始不习惯这点总想在上面运行类似于update和delete的操作那是拿关系型数据库的思路在用HDFS。HDFS的文件是write-once、read-many的一旦写入通常不会修改这会带来一个很大的好处写完后文件不会因为半路崩溃而出现部分修改数据一致性模型变得非常简单批处理任务也因此能放心地重试。3.2 MapReduce任务拆开算再合起来算MapReduce是Hadoop向世界展示并行计算思想的“招牌”。虽然现在跑新任务很少有人直接写MapReduce代码了但理解它的执行流程对你后面理解一切分布式计算框架都有帮助。它的模型非常简单只有两个阶段Map阶段和Reduce阶段。Map阶段负责把输入数据切成很多相互独立的小片每个小片都由一个map任务处理输出的是一堆键值对Map任务之间互不依赖所以可以几百上千个同时跑。Reduce阶段负责把同样键的所有值收集到一起做最终的聚合计算比如求和、计数、求平均。两个阶段中间还有一个必经环节叫Shuffle它做的事是“按key分组并排序”把相同key的所有value从不同map任务结果里归拢到同一个reduce任务去。数据倾斜问题很多时候就出在这——如果某个key特别“热”所有value都堆到同一个reduce里那这个reduce就会慢得像蜗牛。用一个经典的词频统计例子来演示输入是一堆文本文件每一行都交给一个map任务切词输出类似于(“hello”, 1)、(“world”, 1)这种键值对Shuffle把相同单词的键值对归到一起变成(“hello”, [1,1,1,1])最后reduce把这些1全部加起来输出(“hello”, 4)。整个过程就是“拆成很多小活干完再汇总”。MapReduce的优点很突出接口极简只需要实现map和reduce两个函数容错机制直接任何一个任务挂了框架自动在另一台机器上重跑数据一致性由HDFS和框架共同保证。但它的缺点同样明显——中间结果要反复写磁盘完完整整跑一遍WordCount可能要读几十次磁盘延迟能到秒级甚至分钟级。这也决定了它只适合离线批处理撑不起交互式查询和实时流计算后续的Spark才把中间结果放进了内存把速度提了一个量级。3.3 YARN把算力和内存变成可以分配的资源早期Hadoop只有HDFS和MapReduce那个阶段资源管理是混在MapReduce内部的任务需要几核CPU、多大内存全由计算框架自己说了算存储和计算被捆绑在一起。后来大家发现这种设计太封闭除了MapReduce别的计算框架没法复用这套集群。于是YARN被单独拆了出来成为资源调度层。YARN的核心也有两个角色ResourceManager和NodeManager。ResourceManager是整个集群的“裁判”全局掌握每台机器上有多少资源、谁在占用NodeManager是每台机器上的“监工”管理本地资源并将状态上报。当用户提交一个计算任务时ResourceManager会先为这个任务分配一个ApplicationMaster由它负责把任务拆分成多个执行单元再向ResourceManager申请资源最后把任务调度到各个NodeManager上执行。被YARN管理的资源主要有两项CPU核数和内存。为了搞明白这个当年我在配置里踩过不少坑因为默认配置经常按早年那种小内存机器来算而现在的机器动辄32G、64G不改配置很容易导致任务刚启动就被容器溢出杀掉。后面实操部分我会给出一个能跑起来的最小配置。有了YARNHadoop的意义就不再局限于“用MapReduce算数据”了。Spark、Flink这些后起的计算引擎都可以提交到YARN上运行共享同一套HDFS存储和同一批机器资源。换句话说Hadoop变成了一个“存储调度的基础平台”计算到底用哪个引擎你可以自主选择。这也是现在很多人说的“Hadoop生态”的根基。下表是三个核心组件的职责速记方便对比记忆组件职责核心角色一句话类比HDFS分布式存储NameNode / DataNode仓库管理者货架MapReduce分布式计算模型Map Task / Reduce Task拆任务、汇总结果YARN资源调度与分配ResourceManager / NodeManager调度CPU、内存的人4. 亲手把Hadoop跑起来一次最简WordCount的完整现场概念讲再多不如亲手跑一次。这里我带你完整跑一个最小可行的WordCount环境就用一台Linux机器做伪分布式部署——听着“伪”其实就是在一台机器上同时扮演NameNode、DataNode、ResourceManager、NodeManager四个角色。好处是零门槛坏处是它只适合学习验证千万别拿这个配置当生产集群用了。4.1 最小环境准备建议用Linux环境虚拟机、云主机、WSL都行Ubuntu这类发行版最省事。安装之前先确认两件事第一装好JDK 8Hadoop对JDK版本有兼容性要求太新的版本反而可能报编译错误第二准备好一个非root的普通用户后面所有Hadoop进程都用这个用户启动避免权限问题。另外要做一次本机SSH免密登录因为伪分布式模式下脚本会用ssh去连接本机来启动进程。下载安装包时建议直接用官网或者镜像站的稳定二进制包不要自己从源码编译省下大量无谓的时间。解压到某个目录后先只改一个地方就能继续往下在 etc/hadoop/hadoop-env.sh 里设置JAVA_HOME环境变量指向你JDK的安装绝对路径。这一步最容易被忽略很多启动失败的报错都从这个变量没配好开始。4.2 修改四个配置文件伪分布式只需要动四个文件core-site.xml、hdfs-site.xml、mapred-site.xml、yarn-site.xml。为了不出错我建议最小化地只写少量必填项。core-site.xml里最重要的一项是指定NameNode的地址也就是让客户端知道去哪里访问文件系统元数据配置项叫fs.defaultFS值格式类似 hdfs://localhost:9000。hdfs-site.xml里建议把副本数临时改成1因为你只有一台机器默认3会白白做三份副本验证起来也没什么必要。mapred-site.xml里要指定计算框架走YARN配置项是mapreduce.framework.name值写成yarn。yarn-site.xml是纯资源管理项可以先把yarn.nodemanager.resource.memory-mb这类参数调低比如2048MB左右避免默认值过大导致你的测试机器内存不够用。生产集群这些参数要根据机器内存重新测算后面我会讲。改完配置后第一次启动前一定要执行一次格式化操作命令是 hdfs namenode -format。这一步会在NameNode的本地目录生成一个版本标识相当于给HDFS“开荒”。要注意的是这个命令只能对全新的HDFS执行一次如果你在已有数据的集群上重复执行等于把元数据清零再重建极其危险。所有学习环境中最大的一个破坏性误操作就是反复格式化我在实验环境里犯过数据目录直接被清掉那种滋味不想再体验第二次。4.3 启动进程并验证前三件事依次做完了就可以用一条命令启动HDFSsbin/start-dfs.sh再启动YARNsbin/start-yarn.sh。启动完成后通过 jps 命令检查正常情况下你应该看到NameNode、DataNode、ResourceManager、NodeManager这几个Java进程都在。如果缺了DataNode多半是格式化目录和启动目录不一致或者DataNode的clusterID和NameNode对不上处理方式是把数据目录清掉重新格式化如果ResourceManager起不来优先查日志文件logs目录下的输出几乎所有的启动报错都能在里面找到具体原因。进程都在了可以用web界面验证一下。HDFS的监控页面默认在9870端口YARN的资源调度页面在8088端口浏览器打开能看到存活节点数和总资源量。看到这些数字说明你的Hadoop水平已经从“完全看不懂”进入“能自己搭环境”的下一阶段了。4.4 从HDFS上读原始文件并跑WordCount现在你的集群能存储了第一步自然是往HDFS里放数据。用命令行创建目录、把本地文件传上去hdfs dfs -mkdir -p /input hdfs dfs -put test.txt /input/这里要注意HDFS里的路径和本地路径是两套体系很多新人会困惑“文件到底传上去没有”可以用 hdfs dfs -ls /input 确认。接下来处理作业。虽然现在直接写Java的MapReduce程序有点落伍但Hadoop安装包里自带了示例jar包路径一般在 share/hadoop/mapreduce/hadoop-mapreduce-examples-*.jar直接用它能跑一个标准的WordCount。提交命令大致如下hadoop jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-*.jar wordcount /input /output任务提交后你会看到一串日志显示map进度百分比、reduce进度百分比跑完后还会有耗时统计。如果中途出现任务失败别慌最常见的原因是输出目录已经存在——HDFS不允许自动覆盖同名目录所以每次跑之前要么删掉旧输出要么换一个新的输出目录这是初学时最高频的报错之一。跑成功后用 hdfs dfs -cat /output/part-r-00000 看结果看到每个单词后面跟着一个数字恭喜你已经亲手完成了一次分布式计算作业。5. 跑起来只是开始使用中最容易踩的坑与排查思路环境搭好、作业能跑只能算入门。真正在生产环境里用Hadoop坑多到能写一本书。这里我挑四个出现频率最高的典型问题每个都附上我的排查思路和解决建议。5.1 小文件太多比大数据更可怕的是海量小数据很多人一听“大数据”以为只要文件多就行于是把几千个小文件直接塞进HDFS。结果呢NameNode把每个文件的元数据都放在内存里一个小文件大概占到几百字节一万个小文件就是几百MB十万个就是几GB。内存被元数据吃光之后整个集群会变得极其不稳定甚至直接拒绝写入新文件。更麻烦的是计算侧。MapReduce处理任务时一个输入分片通常会对应一个map任务一千个小文件就是一千个map任务每个map任务的启动、调度、清理都有固定开销。启动一千次任务去处理总共才几MB的数据纯粹是灾难。我的建议是进入HDFS之前先做文件合并能合并成一个大文件的尽量合并或者用SequenceFile这类容器格式把多个小文件包起来。几种方案我都试过最终还是觉得“源头治理”最省力——尽量让写入HDFS的每一批文件都足够大比事后做任何合并方案都干净利落。5.2 数据倾斜一眼就能看出来的病却最容易被忽略数据倾斜的症状特别典型整个MapReduce任务有几百个reduce任务其他几十个都跑完了就剩一个或几个reduce在以龟速爬行整个作业的完成时间因此被无限拉长。本质就是某个或某些key的value数量极其庞大全部涌入了同一个reduce而这个reduce注定跑不完。我遇到过一个印象很深的场景统计素材曝光量多数素材一天曝光量在几万到几十万之间但有一两个爆款素材单日曝光量上亿结果这两个key所在的reduce跑了快两小时其他reduce十几分钟就结束了。解决思路一般有三个方向一是加随机前缀或二次聚合把热点key先打散成多个子key分别统计最后再合并一次二是采用更细粒度的分区策略三是从业务角度拆解分析、重新设计分组维度。不管选哪种核心都是让“热点”不要集中在单个reduce里分散才有并行度。5.3 NameNode的内存集群容量的天花板其实在这里初学者常常默认集群容量上限等于所有DataNode磁盘之和这个理解是错的。很多情况下NameNode的内存才是真正决定集群可存文件规模上限的天花板。每个文件、每个文件块都要在NameNode内存里占一条记录文件总数一大NameNode的内存先撑不住。多数生产环境建议是文件规模达到千万级就要给NameNode配大内存甚至做联邦扩展。另外一个办法是把块大小调大——从默认128MB调成256MB甚至512MB文件数量相同的情况下元数据条数直接减半NameNode压力也减小了一半。但块调大也有代价单次计算的并行粒度相应变粗任务调度均衡性会变差所以这个值要结合你文件平均大小和常用计算类型综合权衡。5.4 YARN内存配置最难受默认值通常是给“小机器”写的最后必须点名YARN的内存配置。我见过太多人照着网上教程配然后作业一提交就报容器被kill的错。原因往往就是yarn-site.xml里几个内存参数用默认值但那个默认值是按早年小机器设计的放到现在动辄32G、64G内存的环境里完全不合适分配的内存过大或过小都会出错。推荐的排查路线是先看NodeManager所在机器物理内存再留出系统和其他进程的余量然后把yarn.nodemanager.resource.memory-mb设置为可分配的总内存把yarn.scheduler.maximum-allocation-mb设置成单个容器能申请的最大内存。比如单台机器32G物理内存系统留8G给YARN分配24G单容器最高4G这几个值必须满足“nodemanager配置的总内存大于等于调度器允许的最大单容器内存”这个关系否则大任务提交必然失败。每次调整完配置后重启YARN进程再看8088页面确认总内存是否生效。6. 别急着问“Hadoop是不是过时了”和Spark、Flink的真实关系现在网上有很多人问“Hadoop是不是过时了”你要是只看这类问题的回答很容易产生一个误解Hadoop已经废了。事实上这句话真正想表达的意思只是“MapReduce过时了”而Hadoop这个体系本身并没有消亡反而以另外一种形态活在整个大数据生态的最底层。你一定听过Spark、Flink这些计算引擎的名字它们和Hadoop的关系更像是“住户”和“小区”HDFS是小区的基础设施管存储YARN是物业管资源Spark和Flink则是住进来的住户用这批资源跑更快的计算。所以现在生产环境里最常见的部署方式是存储还是HDFS调度还是YARN但计算引擎已经换成了Spark跑批处理能比MapReduce快一到两个数量级如果要做实时流处理可以再上Flink。这些引擎照样会去读HDFS上的数据所以Hadoop的核心基础设施地位依旧稳固。那是不是所有场景都应该上Hadoop呢恰恰相反我把话放这儿如果你的数据量只有几十GB到几百GB单机数据库加个集群方案就够用了强行上Hadoop纯属给自己找罪受。Hadoop适合的数据量级至少是几个TB以上、需要垂直维度水平扩展、且能接受秒级到分钟级延迟的批处理场景。如果你的诉求是毫秒级响应或者是要快速支持即席交互查询那应该考虑关系型数据库、列式存储或专门的分析引擎而不是把Hadoop当成万能药。真正让Hadoop在生产里站稳脚跟的还有它那套“低成本高可靠”的组合廉价服务器凑起来就能用单点故障不会丢数据数据备份天然多副本。这个定位在所有新技术层出不穷的今天依然有价值。所以我给的建议很朴素新项目你可以直接用Spark和HDFS的组合也可以直接上云用对象存储不一定非得部署完整的Hadoop全家桶但如果你是奔着理解分布式存储和计算框架的原理去的把Hadoop拆开从头到尾过一遍依然是性价比最高的入门路径。7. 我对Hadoop实际操作中的最后一点体会关于Hadoop我觉得最有价值的东西不是它本身有多强而是它逼着你想清楚几个问题数据从哪里来存在哪里谁来算怎么保证挂了还能重来。这些东西看起来都是“常识”但只有亲手跑过一遍踩过配置文件的坑、见过数据倾斜的惨状、被NameNode内存逼到束手无策之后才会真正内化成能力。最后分享一个很小的经验不管你是要学习还是要上生产一开始都不要追求“全功能”先最小化跑通一条线最重要。Hadoop有几十个参数和一堆高级功能你不可能在同一时刻全部搞明白。先把本地伪分布式跑通再逐步加机器、加副本、开高可用每一步的改变都保持在一个可控范围内。我当年就是太贪心一上来就想配高可用集群结果配置文件错成一团麻反倒连最基础的作业都跑不起来。慢慢来Hadoop的复杂其实比它看上去要好懂得多。
阅读完成 · 觉得有帮助?
咨询建站