简介这是围绕Hadoop与Spark生态的大数据处理与案例分析资料面向大数据初学者、数据分析师及平台运维人员帮助读者理解常用组件与实际项目的结合方式。文档内容涉及HDFS、MapReduce、HBase、Hive、Spark、Storm、Mahout等核心工具并结合电信网络优化、移动计费账单、银联票据平台、银行记录系统、交通违章、区域医疗等真实业务场景展开分析便于将理论知识映射到企业级应用中。包体信息较为精简整个资源仅包含1个docx文件压缩包大小约15KB轻量易保存适合作为随时查阅的要点式笔记。当前已有502人学习下载虽然体积不大但覆盖了Hadoop生态的主要知识点和案例思路尤其适合需要快速建立知识框架或准备相关面试、项目汇报的读者。借助其中提炼的案例方法和处理流程读者可以迁移到自身的大数据项目设计与问题排查中提升实践效率。1. hadoop、spark 大数据处理与案例分析先把两个生态拆开再动手「hadoop、spark 大数据处理与案例分析」这类标题在大数据岗位 JD 里出现频率很高但多数人拿到后的第一个动作是装环境装完跑通 wordcount 就停住再没往前走一步。先说一个反直觉的结论Hadoop 和 Spark 不是竞品而是上下级关系——Hadoop 用 HDFS 把数据存下来用 YARN 把计算资源分出去Spark 负责在内存里把计算做快。所谓案例分析也不是把官方示例点一遍而是把一堆 JSON、CSV 变成你要的报表并且讲得清执行计划为什么长这样、内存参数为什么要那样设。这篇文章会从 Hadoop 伪分布式搭建、Spark 集群与内存参数、JSON 数据分析案例一直写到最容易翻车的 5 个排查经验适合正在做课程设计、准备大数据面试或想一个人撑起一条完整小链路的读者。2. Hadoop 伪分布式搭建三件套分工、InputSplit 与最小可运行集群先搭 Hadoop 不是因为 Spark 离不了它而是因为生产环境里 Spark 绝大多数跑在 YARN 上你至少要有一个看得见、摸得着的集群形状。伪分布式是把 NameNode、DataNode、ResourceManager、NodeManager 塞进同一台机器它不适合压测但足够把 HDFS、YARN、MapReduce 之间的关系和文件读写流程顺一遍。下面这部分会先讲三个组件谁在干活再给一套能直接执行的搭建步骤最后留一个自检方法。2.1 HDFS、YARN、MapReduce 到底谁在干活HDFS 是存储层。NameNode 管元数据DataNode 管数据块文件默认按 128MB 切块存储。写入流程是先问 NameNode 拿地址再往 DataNode 做流水线复制。YARN 是资源调度层ResourceManager 做全局调度NodeManager 在节点上起容器ApplicationMaster 负责把单个应用翻译成资源申请。MapReduce 是计算框架负责把任务切成逻辑分片再调度执行。这里有个面试高频问题在一个运行的 Hadoop 任务中什么是 InputSplitInputSplit 是逻辑切分Block 是物理存储单位默认情况下一个 Split 对应一个 Block但通过mapreduce.input.fileinputformat.split.maxsize可以把 Split 调大调小。Map 的并行度由 Split 个数决定跟文件里有多少行数据没关系。很多新手以为「文件大并行度就高」其实是「分片多并行度才高」这也是为什么小文件过多时 Map 任务会被撑爆。2.2 伪分布式搭建步骤JDK、SSH、五个配置文件与一次性格式化以 Hadoop 3 系加 JDK 8 为例先建一个独立用户跑 Hadoop避免 root 操作带来的目录权限问题然后配置本机免密 SSH。start-dfs.sh 会通过 SSH 拉远程进程哪怕目标是 localhost 也一样要走 SSH这一步漏了后面会直接报错。# 1. 创建独立用户并切过去 sudo useradd -m hduser sudo usermod -aG sudo hduser su - hduser # 2. 生成 SSH 密钥并配置本机免密 ssh-keygen -t rsa -P -f ~/.ssh/id_rsa cat ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys # 3. 追加环境变量到 ~/.bashrc export JAVA_HOME/usr/lib/jvm/java-8-openjdk-amd64 export HADOOP_HOME/opt/hadoop export PATH$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin环境变量里 JAVA_HOME 必须真实存在并写死不要依赖 shell 自己推断。解压后的 Hadoop 目录最好用固定路径比如 /opt/hadoop后续所有配置都基于它。接下来修改$HADOOP_HOME/etc/hadoop/下的五个文件。核心是这组配置!-- core-site.xml -- configuration property namefs.defaultFS/name valuehdfs://localhost:9000/value /property property namehadoop.tmp.dir/name value/data/hadoop/tmp/value /property /configuration !-- hdfs-site.xml -- configuration property namedfs.replication/name value1/value /property property namedfs.namenode.name.dir/name value/data/hadoop/namenode/value /property property namedfs.datanode.data.dir/name value/data/hadoop/datanode/value /property /configurationfs.defaultFS决定了所有 HDFS 路径的默认前缀。dfs.replication1是伪分布式必须写的单机情况下 3 副本会让数据在同一个节点上打转还会白白占两倍磁盘。dfs.namenode.name.dir和dfs.datanode.data.dir建议放到独立数据目录不要落在系统盘的临时目录里否则重启系统后元数据丢了会很被动。mapred-site.xml 和 yarn-site.xml 各有一个必须写的参数。mapred-site.xml 里写mapreduce.framework.nameyarn告诉 MapReduce 用 YARN 做资源调度yarn-site.xml 里写yarn.nodemanager.aux-servicesmapreduce_shuffle声明节点管理器要加载 shuffle 辅助服务reduce 阶段拉数据靠它。# 首次启动集群前必须格式化 NameNode只做一次 hdfs namenode -format start-dfs.sh start-yarn.sh jps格式化只做一次这是最关键的纪律。二次格式化不会把旧集群复活反而会让新生成的 clusterID 和数据目录里旧 VERSION 文件对不上直接导致 DataNode 起不来。想要后悔药的话正式集群里要备份 fsimage 目录而不是重新格式化。2.3 用自带 wordcount 自检确认存储、调度和计算都通进程起来后用 jps 验证正常应该看到 NameNode、DataNode、ResourceManager、NodeManager、SecondaryNameNode。Web 端有两个入口Hadoop 3.x 的 NameNode UI 是 9870 端口YARN ResourceManager UI 是 8088 端口。如果连 8088 都打不开多半是 ResourceManager 没起来先看日志再谈别的。再把一份测试文件放进 HDFS跑一次自带的 wordcount。这个作业能走到 SUCCEEDED说明存储、调度、计算三层都通了。跑完后启动 JobHistory 服务这样后续 Spark 作业结束之后还能从 UI 里回看历史记录。hdfs dfs -mkdir -p /input hdfs dfs -put /home/hduser/test.txt /input/ hadoop jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-*.jar \ wordcount /input /output hdfs dfs -cat /output/part-r-00000如果只是想在虚拟机里快速出一个能演示的环境也可以直接拉一个 Hadoop 的 docker 镜像跑伪分布式但镜像里 hostname 经常被写死节点注册、数据目录挂载都会多出隐藏变量。手工按这套步骤走一遍反而能把 HDFS、YARN、MapReduce 之间谁调谁的关系看得更清楚。Windows 上想直接用网上下载的已编译 jar 包还要在 HADOOP_HOME/bin 里放对应版本的 hadoop.dll 和 winutils.exe这个坑放后面专门说。3. Spark 集群安装与内存配置从 standalone 到 yarn-cluster 的取舍Spark 单独装不难难的是决定让它用什么形态跑。local 模式跑 demo 很顺手但课程设计或面试复盘时你最好能说清楚 standalone 和 YARN 的区别以及为什么生产上通常选后者。这一章先讲运行模式怎么选再给最小安装步骤最后给一张内存参数表——这里是最容易翻车的地方。3.1 运行模式怎么选local、standalone 与 YARN 的付出和得到local 模式是进程内线程不涉及资源调度适合调试代码逻辑。standalone 模式用 Spark 自带的 Master 和 Worker适合没有 Hadoop、又想跑多节点的小团队部署简单但没有 YARN 的队列隔离和统一账号体系。yarn 模式才是生产常态集群资源由 ResourceManager 统一分配Spark 作业作为一个 Application 申请容器任务跑完资源自动回收。在 YARN 下还分两种。yarn-client 模式 driver 跑在提交任务的客户端开发调试方便Spark UI 立刻能看到yarn-cluster 模式 driver 跑在集群内适合定时调度和长时间作业客户端提交完就可以关掉。要跑本篇文章的案例yarn-client 就行如果是课程设计做「每天定时报表」这类演示用 yarn-cluster 更完整。版本选择上有个硬约束Spark 3 系要下载spark-3.x-bin-hadoop3这种带 hadoop3 标识的预编译包配 Hadoop 3 集群才不会有 native 库跑偏的问题。3.2 最小安装与 pyspark 自检先确认 SparkSession 能拿到资源Spark 安装本身是解压即用但要让 Spark 真正跑在 YARN 上必须让它找到 Hadoop 的配置。很多人配了 SPARK_HOME 就以为万事大吉结果pyspark --master yarn一提交就报找不到集群原因就是 HADOOP_CONF_DIR 没写。export SPARK_HOME/opt/spark export PATH$PATH:$SPARK_HOME/bin export HADOOP_CONF_DIR$HADOOP_HOME/etc/hadoop export PYSPARK_PYTHONpython3 # 用 yarn-client 模式启动交互式 shell验证能拿到集群资源 pyspark --master yarn --deploy-mode client启动之后写一个最小脚本读 HDFS 上的一行 JSON打印 schema。这个动作会触发 SparkSession 初始化、去 ResourceManager 申请 driver 资源、走 HDFS 协议读文件整条链路都验证一遍。from pyspark.sql import SparkSession spark SparkSession.builder \ .appName(smoke_test) \ .getOrCreate() df spark.read \ .option(encoding, UTF-8) \ .json(hdfs://localhost:9000/data/sample.json) df.printSchema() df.show()如果这一步能正常打印出字段结构说明 Spark 和 Hadoop 的衔接没有问题。常见的报错是 ApplicationMaster 起不来或者一直等待大概率是内存配置问题看下一节。3.3 内存配置executor、driver、overhead 必须一起算Spark 内存不是只调一个executor-memory就完事。executor 是执行任务的进程driver 是跑 main 函数的进程executor 还要额外占用堆外内存给 Java 直接内存和线程开销。下面这张表是核心参数参数默认值什么时候动spark.executor.memory1G数据量大、GC 频繁时调大spark.executor.memoryOverheadmax(384MB, 10% of heap)用 Python UDF 或大量序列化时容易爆调大到堆的 15%-20%spark.driver.memory1Gcollect 回 driver 的数据量大时调大spark.executor.cores1单任务处理太长时按节点核数调到 2-3spark.sql.shuffle.partitions200数据量大但单个任务跑太久时调大spark.default.parallelism由 shuffle 分区决定建议设为集群总核数的 2-3 倍实际提交作业时这些参数要一起算总量。比如单节点 16G 内存留给操作系统和其他进程约 20%YARN 可分配约 12G。executor 4G 加 overhead 0.4G启动两个 executor 已经占掉 8.8G还要给 ApplicationMaster 和 driver 留余量。很多任务一直 ACCEPTED 不跑就是 executor 申请的内存上限超过了yarn.scheduler.maximum-allocation-mb不是代码卡住是资源根本申请不下来。spark-submit \ --master yarn \ --deploy-mode cluster \ --num-executors 2 \ --executor-cores 2 \ --executor-memory 4g \ --driver-memory 2g \ /home/hduser/order_analysis.py内存配置不是越大越好。executor 太大容器申请不下来executor 太小 shuffle 又频繁落盘。常见的可行区间是单 executor 2G 到 8Gcore 数 2 到 4具体看节点总资源。判断标准很简单任务能稳定跑完Spark UI 里各 stage 的时间分布均匀GC 时间不超过任务时间的 10%就是合理配置。4. 用 PySpark 做一份可复现的数据分析案例从 JSON 读取到 TopN 输出案例分析是标题里最容易让人空手而归的部分。所谓案例不是把官方示例跑一遍而是要你面对一份真实形态的数据完成清洗、聚合、排序、写回这一整套动作。这里选订单流水 JSON 作为例子因为 JSON 是业务系统最常见的半结构化格式而且spark.read.json的坑足够多能顺手把 schema 推断和编码问题都过一遍。4.1 案例怎么选订单流水里藏着的三个分析动作假设 HDFS 上有一批订单流水字段包括 order_id、user_id、order_time、amount、category、province。业务目标是三个清洗出有效订单、按月统计销售额、找出每年销售额 Top 5 的品类。这三个目标分别对应 DataFrame 的过滤去重、分组聚合、窗口排名正好覆盖日常数据分析的高频操作。为什么这个案例适合用来完整跑通链路因为它在数据源、中间结果、最终输出上都存在容易翻车的点JSON 文件可能是多行结构amount 字段可能有负数order_time 可能是字符串groupBy 后分区数对结果文件数量有直接影响。这些问题不跑一遍真实数据靠看文档是体会不到的。4.2 完整代码读 JSON、清洗、聚合、排序、写回from pyspark.sql import SparkSession from pyspark.sql.functions import col, to_date, year, month, sum as _sum, desc, row_number from pyspark.sql.window import Window spark SparkSession.builder \ .appName(order_analysis) \ .config(spark.sql.shuffle.partitions, 10) \ .getOrCreate() # 1. 读取 HDFS 上的订单 JSONschema 由 Spark 自动推断 df spark.read \ .option(encoding, UTF-8) \ .json(hdfs://localhost:9000/data/orders/) # 2. 清洗剔除金额为空或为负的记录订单号去重 df_clean df.filter( col(amount).isNotNull() (col(amount) 0) ).dropDuplicates([order_id]) # 3. 把时间字符串转成日期类型方便按月聚合 df_clean df_clean.withColumn(order_date, to_date(col(order_time))) # 4. 按月统计销售额 monthly df_clean.groupBy( year(col(order_date)).alias(year), month(col(order_date)).alias(month) ).agg(_sum(amount).alias(total_amount)) # 5. 每年内按品类汇总销售额并按年度排名取 Top 5 category_summary df_clean.groupBy( year(col(order_date)).alias(year), col(category) ).agg(_sum(amount).alias(total_amount)) cat_window Window.partitionBy(year).orderBy(desc(total_amount)) category_top category_summary \ .withColumn(rank, row_number().over(cat_window)) \ .filter(col(rank) 5) # 6. 写回 HDFS按年分区输出为 parquet category_top.coalesce(1) \ .write.mode(overwrite) \ .format(parquet) \ .partitionBy(year) \ .save(hdfs://localhost:9000/data/result/category_top/)代码里的几个点要说明。filter、dropDuplicates、withColumn 都是懒执行直到 count、show 或 write 这类动作发生才真正触发计算。groupBy 会触发 shufflespark.sql.shuffle.partitions设为 10意思是 shuffle 之后分成 10 个分区分区太多文件碎片多分区太少单任务数据量大。coalesce(1)是把结果合并成单分区写出适合演示场景但数据量大时不建议用它会打破并行度应该改成repartition(4)配合write.partitionBy或者直接按原分区数写出。窗口函数Window.partitionBy(year)的意思是排名只在单年内比较不会跨年混排。row_number()生成连续排名配合 filter 取前 5 名比先排序再 take 更符合 SQL 习惯。4.3 结果怎么自查count、抽样与 Spark UI 三段验证跑完不能只看 SUCCEEDED。先把结果读回来按年做 count和清洗前的数据量对比确认过滤比例合理。然后抽样一个品类手算一下金额合计对照输出保证没有跑偏。最后打开 Spark UI 的 Stages 页看 Shuffle Read 时间和计算时间的比例。shuffle 时间占比大于计算时间说明分区数偏少或者 key 分布不均后续调优方向就清楚了。5. Hadoop 与 Spark 踩坑排查5 个最容易翻车的环境环节环境问题会花掉入门阶段 70% 的时间。下面这 5 条不是全部但是伪分布式、spark on yarn 和 JSON 案例分析里最常遇到的典型情况按现象、原因、解决三步写方便直接对照排查。5.1 格式化后 DataNode 起不来clusterID 对不上现象start-dfs.sh 执行完jps 只有 NameNode没有 DataNode。日志里出现 Incompatible clusterIDs 之类的内容。原因格式化 NameNode 之后新生成的 clusterID 和 DataNode 数据目录里旧的 VERSION 文件对不上。常见于格式化过一次之后没有清数据目录或者改过hadoop.tmp.dir后旧数据还留在原来的位置。解决停掉 dfs把dfs.namenode.name.dir与dfs.datanode.data.dir对应的数据目录清空再重新格式化并启动。正式环境里这属于高危操作动手前先把 NameNode 的元数据目录完整备份格式化没有后悔药。5.2 Spark 任务一直 ACCEPTEDexecutor 申请不下来现象用yarn application -list看 App 一直处于 ACCEPTED 状态Spark UI 里 Executors 数量为 0。日志里没有明显异常就是一直等。原因executor 申请的内存和虚拟核数超过了 YARN 单个容器允许的上限ResourceManager 无法满足申请条件任务卡在资源调度阶段。解决查yarn-site.xml里的yarn.scheduler.maximum-allocation-mb把 executor memory 加 overhead 后和这个上限对比。要么调小--executor-memory要么把上限调大。改完必须重启 YARN 才生效光改配置不重启会让人误以为玄学。5.3 读 JSON 翻车多行 JSON 与编码不一致现象一条记录被拆成两行解析或者中文变成乱码schema 推断出来的字段和文件实际结构对不上。原因spark.read.json默认按行读取要求 JSON Lines 格式每个对象单独一行。如果源文件是格式化输出、一条数据占多行默认读取方式就会解析错位。编码上如果文件不是 UTF-8中文基本必乱。解决源文件统一转成一行一个 JSON 对象确实无法转换的读的时候加.option(multiline, True)。编码统一用.option(encoding, UTF-8)GBK 文件先在源头转好不要在 Spark 里迁就旧格式。这是 spark 读取 JSON 场景里最高频的坑。5.4 Container killed by YARN虚拟内存超限现象作业跑到一半 executors 被杀日志提示 exceeding memory limits堆内存明明没有满。原因executor 进程的堆外内存、线程栈、Python 进程缓冲都算在容器内存里spark.executor.memoryOverhead默认只有堆内存的 10%这些开销挤爆了限额。解决把 overhead 调到 executor memory 的 15%-20%。测试环境可以临时调yarn.nodemanager.vmem-pmem-ratio2.5放宽虚拟内存检查但生产上不建议靠放宽检查混过去先想清楚是不是内存配置不合理。5.5 Windows 上已编译 jar 包HADOOP_HOME 配了还是报错现象网上下载别人编译好的 Hadoop jar 包在 Windows 上设置了 HADOOP_HOME 环境变量运行时报 Could not find or load main class或者提示 failed to locate the winutils binary。原因Hadoop 在 Windows 上需要本地库支持HADOOP_HOME/bin 里必须存在对应版本的 hadoop.dll 和 winutils.exe且版本要和 jar 编译时一致。解决确认 HADOOP_HOME 路径正确下载对应版本的 winutils 工具放进 bin 目录关闭命令行重新打开再跑。这不算玄学native 库版本对不上程序启动阶段就会崩。有条件的话整套环境放在 Linux 虚拟机上做能直接跳过这一类问题。# 排查资源相关问题先拿 App ID再取具体日志 yarn application -list yarn logs -applicationId application_xxxx_0001 | grep -i -E error|exceptionyarn logs能查到 executor 和 driver 的完整日志这个命令依赖 YARN 开启了日志聚合也就是yarn.log-aggregation-enabletrue。伪分布式里建议打开否则任务一结束容器日志就没了排查问题会很难受。6. 进阶验证用 Spark UI 反推内存与并行度别再瞎调参6.1 从 Executors 页判断并行度任务结束后到 YARN ResourceManager 的页面点开 App ID进入 Spark UI。先看 Executors 页的 Active Tasks。如果活跃任务数长期低于你申请的 executor cores 总量说明并行度不够典型调法是调大spark.sql.shuffle.partitions或者对输入数据先做一次repartition扩分区。反过来如果任务数很多但每个任务处理时间极短说明分区过碎要降低分区数减少调度开销。6.2 从 Stage 页看数据倾斜Stages 页看两个数字Shuffle Write 和 Shuffle Read。Shuffle Read 时间远大于计算时间说明数据倾斜或者 key 分布不均。常见做法是给热点 key 加盐拆分比如把高频的 user_id 拼个随机后缀分摊到不同分区。还有一个检查点看 Event Timeline 里任务是否存在长时间空转空转多半是资源等待不是代码问题。我自己踩过的一个案例处理一个 2T 的聚合任务执行了四个小时。后来把 executor cores 从 1 调到 3shuffle 分区从 200 调到 480改动只有几行配置作业从 4 小时缩短到 40 分钟。原理就是并行度提上去了每个分区处理的数据量降下来了。但这里有个前提——如果不先看一眼 Spark UI我根本不知道瓶颈在 CPU 没吃满而不是内存不够。从伪分布式到现在我养成的习惯是每次调参前先截一张 UI 图记下当时的瓶颈在哪个阶段调完再截一张对比。你可以把这个方法用在课程设计或工作环境里判断标准简单粗暴任务稳定跑完、Stage 时间分布均匀、GC 时间不超过 10%。如果同时满足这三条说明参数已经在一个健康的区间里不用再折腾内存配置。希望帮到你。本文还有配套的精品资源点击获取