云主机四节点Hadoop集群与OBS对象存储大数据实验链路
简介面向高校大数据课程学习者和华为云初学者这份实验报告围绕云上大数据平台的部署与查询展开覆盖弹性云服务器、OBS对象存储、Hadoop与Spark集群搭建以及BigData Pro综合方案和交互式查询等实践环节。包内含1个docx文档大小约4.36MB以实验记录形式组织便于按实验模块查阅环境准备、节点配置、集群互联和查询验证等内容。目前已有2541人学习说明其在课程实验与入门实践中有一定参考价值。读者可从中了解ECS与OBS的协同配置、多节点SSH互信与Hadoop集群搭建流程、Spark环境配置及与OBS互联的测试思路也能看到BigData Pro环境下从资源购买到集群管理的完整链路以及使用SQL进行大规模数据探索的基本方法适合用作实验复盘和操作对照。1. 云主机跑 big data这份实验报告真正值得抄的是那条完整链路四台云主机、一个对象存储桶、一套 Hadoop、一个 Spark把这几样东西串起来就是一份典型云上 big data 大数据实验报告的全部骨架。很多人拿到这类资源第一反应是翻到最后看结论其实真正值钱的是中间那段集群搭建与对象存储互联的操作序列——它决定了后面所有实验能不能跑起来也决定了你踩坑时有没有参照物。这份报告覆盖的四个实验分别是云主机实现大数据、云服务实现大数据、BigData Pro 综合实验和大数据交互式查询拆开看是四个任务连起来是一条从裸机分配到 SQL 出结果的完整链路。它适合正在做课程大作业的学生也适合第一次把本地 Hadoop 搬到云上的工程师——本地集群和云上集群最大的差别不在软件而在网络拓扑、密钥权限和对象存储这三件事上。2. 四节点拓扑与云资源选型ECS 规格、VPC 网段和 OBS 桶怎么定动手之前先把拓扑定下来比装到一半发现内存不够再重建要省事得多。这一章讲的是资源账几台机器、什么规格、放哪个子网、桶开在哪个区域以及这些选择在后面的 Hadoop 和 Spark 阶段会带来什么连锁反应。2.1 为什么是四节点而不是三台或八台最小可验证的 Hadoop 集群其实两台就够一台当主节点跑 NameNode 和 ResourceManager一台当从节点跑 DataNode 和 NodeManager。但这样做有两个问题一是副本数只能设 1等于没验证 HDFS 的容错逻辑二是所有角色挤在一台机器上内存稍紧就容易出现 DataNode 被 NodeManager 抢资源后假死的情况排查起来非常费劲。四节点是比较舒服的分法node1 承担 NameNode、SecondaryNameNode、ResourceManagernode2 到 node4 只做 DataNode 和 NodeManager。副本数可以设 2坏一台仍有完整数据同时三台从节点的算力也足够跑 wordcount 和几个小的 Spark 任务。八节点当然更接近生产但对课程实验来说纯属浪费额度而且每多一台机器SSH 互信、hosts 维护、配置分发的工作量都线性增长。规格上有个血泪经验主节点和从节点不要用同一个规格。主节点内存吃紧会直接导致集群启动失败从节点内存吃紧最多是任务变慢。我一般会这么配节点角色vCPU / 内存系统盘说明node1NameNode / SecondaryNameNode / ResourceManager4 核 8G高 IO 60G元数据与调度都在这里内存不能省node2DataNode / NodeManager2 核 4G高 IO 60G数据盘按数据量估实验阶段 60G 够用node3DataNode / NodeManager2 核 4G高 IO 60G与 node2 同规格方便横向对比node4DataNode / NodeManager2 核 4G高 IO 60G也可临时兼做 Spark 客户端磁盘类型要选高 IO 或者 SSD 类普通盘在格式化 NameNode、写入大量小文件时那个等待时间会让人怀疑人生。四台机器必须落在同一个 VPC、同一个子网内最好连可用区都一致跨可用区通信虽然能通但延迟抖动会让 YARN 的心跳超时判断变得很玄学。还有一个容易被忽略的点购买时一次性把四台都买在同一安全组下或者先建好安全组再挂机器。后面再改安全组规则如果改错了方向机器之间的 SSH 会突然断掉而你又没有控制台之外的入口只能重置。2.2 OBS 桶与并行文件系统区域、命名和密钥三件事对象存储这一层最容易出问题的不是代码是配置。先把三件事定死桶在哪个区域、桶叫什么名字、密钥怎么生成。桶的区域必须和 ECS 同区域。同区域内网访问走的是内网端点不计公网流量费延迟也低跨区域访问不但慢还会产生额外的流量费用实验做到一半发现账单异常往往就是这个原因。桶名全局唯一只能用小写字母、数字和短横线长度 3 到 63 个字符命名时最好带上用途前缀比如bdp-lab-2024避免和别人撞名后反复重试。密钥这块控制台上创建访问密钥后会得到一个包含 AK/SK 的 CSV 文件这个文件只允许下载一次关掉页面就再也拿不到了只能删除重建。所以下载后立刻存到本地密码管理器或者加密盘里。AK 是身份标识SK 是签名密钥两者都不要写进代码仓库实验场景下用环境变量或者配置文件加 600 权限最稳妥。如果实验涉及 Spark 或 Hive 直接读写建议直接用并行文件系统类型的桶。它对外提供类 POSIX 语义重命名、追加这类操作的行为比普通对象桶更接近本地文件系统Spark 写临时文件时不容易出现 rename 失败。普通桶也能用只是在_temporary目录的处理上要多留个心眼。参数建议值说明区域与 ECS 同区域跨区域会产生流量费且延迟高桶类型并行文件系统类 POSIX 语义适合大数据读写访问方式仅内网端点公网端点实验阶段不必开密钥存放环境变量 / 配置文件 600不落代码库不写进 shell 历史提示把 AK/SK 写进~/.bash_history是新手最常犯的错用export之前先set o history或者干脆写进独立的env.sh再source。2.3 安全组与 hosts把内网互通一次做对安全组是云上和本地集群差别最大的地方。本地机器默认互相能通云上默认全封。四台机器要组成集群必须放通内网段之间的若干端口而不是简单地放通 0.0.0.0/0。正确的做法是新建一个安全组入方向规则里把源地址写成子网网段比如192.168.0.0/24然后逐条放通需要的端口。这样即使某台机器误开了公网 IP也不会把 HDFS 的 9000 端口暴露出去。需要的端口大致是这些端口用途22SSH 与配置分发9000HDFS NameNode RPC9870NameNode Web UI9864 / 9866DataNode HTTP / 数据传输8088YARN ResourceManager Web UI8030-8033YARN 调度相关 RPC7077 / 8080 / 4040Spark 集群模式与 UI配置完安全组再统一写 hosts。这一步必须在装 Hadoop 之前做完因为 Hadoop 的配置文件里到处是主机名等装完再改主机名会导致 DataNode 注册不上。四台机器执行同一段命令# 四台机器分别执行hostnamectl 后的名字各自改 hostnamectl set-hostname node1 # 关闭防火墙云上由安全组负责机器内 firewalld 会干扰端口通信 systemctl stop firewalld systemctl disable firewalld # 写入统一的 hosts四台机器内容完全一致 cat /etc/hosts EOF 192.168.0.10 node1 192.168.0.53 node2 192.168.0.169 node3 192.168.0.77 node4 EOF这里用EOF而不是EOF是为了让变量不被提前展开内容原样写入。IP 全部用内网地址不要写公网地址——一旦 hosts 里是公网 IPHadoop 的 DataNode 会通过公网互相注册走的是公网带宽延迟高还收费而且公网 IP 在重启后可能变化集群直接崩。注意改完 hostname 要重新登录一次 shell否则hostname命令显示的可能是旧值后续ssh node2之类的操作会用到旧的解析结果。3. Hadoop 集群落地从 OpenJDK 到 wordcount 跑通的十四个配置项资源准备好了接下来是最费时间的部分。这一章的每一步都能直接照抄但抄之前建议先看清每个参数为什么这么填因为实验报告里那些配置项在换机器规格、换 Hadoop 版本之后不一定还能用。3.1 环境基线OpenJDK、时间同步和安装包分发Hadoop 对 JDK 的要求比想象中严格。2.x 和 3.x 系列在 JDK 8 上最稳JDK 11 部分版本会有反射相关的警告JDK 17 则直接跑不起来。所以统一装 OpenJDK 8四台机器版本必须完全一致否则编译出来的 class 版本不匹配任务会报UnsupportedClassVersionError。在线安装是最省事的方式前提是机器能访问软件源。如果实验环境的机器只通了内网那就得先在一台机器上下载好 rpm 包再用 scp 分发。四台机器分别执行# 安装 OpenJDK 8四台机器都要执行 yum install -y java-1.8.0-openjdk java-1.8.0-openjdk-devel # 确认版本四台输出应完全一致 java -version # 配置 JAVA_HOME写进全局 profile 避免每次登录都要 export echo export JAVA_HOME/usr/lib/jvm/java-1.8.0-openjdk /etc/profile echo export PATH$JAVA_HOME/bin:$PATH /etc/profile source /etc/profilejava-1.8.0-openjdk-devel这个包不能省只装 JRE 的话后面编译 Java 程序会失败。路径/usr/lib/jvm/java-1.8.0-openjdk是软链接实际指向带版本号的目录用它比用真实路径更保险升级小版本不会失效。时间同步也顺手做掉。四台机器时间差超过几分钟YARN 的资源申请就会莫名其妙被拒日志里只留下一句含糊的InvalidResourceRequestException。实验环境里直接用 chrony 指向同一个内网时间源就行或者至少保证四台机器都在同一个时区、误差在一分钟内。安装包分发用 scp 就够了。把 Hadoop 压缩包传到 node1 的/opt/soft下解压到/opt/module然后循环分发# 在 node1 上执行把解压好的目录同步到其余三台 for h in node2 node3 node4; do scp -r /opt/module/hadoop-2.7.7 root$h:/opt/module/ done解压后先别急着配在 node1 上执行一次bin/hadoop version确认它能读到你设置的JAVA_HOME。如果报JAVA_HOME is not set说明hadoop-env.sh里的配置没生效这一步一定要在分发前解决否则四台机器都得改一遍。3.2 四节点 SSH 互信一条循环搞定但有两个前提Hadoop 的启动脚本靠 SSH 去各节点拉进程所以 node1 必须能免密登录到 node2、node3、node4同时也要能免密登录自己。其他三台之间是否互信取决于你后续要不要从从节点发起操作实验阶段建议四台两两互信省得后面 Spark 的 worker 启动时卡在认证上。第一步是生成密钥对。四台机器分别执行直接回车不设密码短语# 四台机器分别执行-N 表示空密码-f 指定路径 ssh-keygen -t rsa -b 2048 -N -f ~/.ssh/id_rsa # 确认权限这是免密失败最常见的原因 chmod 700 ~/.ssh chmod 600 ~/.ssh/id_rsa chmod 644 ~/.ssh/id_rsa.pub权限这一步是玄学重灾区。.ssh目录给 755 或者私钥给 644SSH 会直接拒绝使用这对密钥日志里只写Authentication refused: bad ownership or modes不提具体是哪个文件。所以每次改完权限用ls -l确认一遍再往下走。第二步是分发公钥。一条循环就能搞定前提是先把每台机器的/etc/hosts配好并且当前 shell 能解析这些主机名# 在 node1 上执行把本机公钥追加到四台机器的 authorized_keys for h in node1 node2 node3 node4; do ssh-copy-id -o StrictHostKeyCheckingno root$h done # 四台机器都做一遍同样的循环才能两两互信 # 验证任意两台之间互相 ssh不应出现密码提示 ssh node2 hostname-o StrictHostKeyCheckingno是为了跳过首次连接的指纹确认批量操作时很有用。验证环节别只看 node1 到其他节点随便挑一台从节点反向登录 node1 试一次能发现单向信任的问题。还有一个隐蔽的坑第一次ssh某台机器时如果没有输入 yesknown_hosts里就没有记录后面 Hadoop 脚本用-o BatchModeyes去连接会直接失败所以验证阶段务必把四台两两连一遍。3.3 核心配置文件改哪几个参数、为什么改Hadoop 的配置文件看着多真正必须改的就那么几个。下面这四组是底线剩下的用默认值基本能跑。core-site.xml里最关键的是文件系统入口。这个地址写什么hadoop fs -ls /就访问什么configuration property namefs.defaultFS/name valuehdfs://node1:9000/value /property property namehadoop.tmp.dir/name value/opt/module/hadoop-2.7.7/data/tmp/value /property /configurationfs.defaultFS用主机名而不是 IP这样即使内网 IP 变了只要 hosts 更新就还能用。hadoop.tmp.dir必须显式指定到一个有足够空间的目录默认值在/tmp下机器重启后大概率被清空格式化信息一丢集群就起不来了。hdfs-site.xml决定副本数和元数据存放位置configuration property namedfs.replication/name value2/value /property property namedfs.namenode.name.dir/name value/opt/module/hadoop-2.7.7/data/namenode/value /property property namedfs.datanode.data.dir/name value/opt/module/hadoop-2.7.7/data/datanode/value /property /configuration三台 DataNode 的情况下副本数填 2 是折中填 1 失去容错意义填 3 意味着任何一台下线都没法写入新块反而降低了可用性。目录分开写是必须的NameNode 和 DataNode 的数据混在一个目录格式化时容易误删。yarn-site.xml决定资源调度两个参数必须改configuration property nameyarn.resourcemanager.hostname/name valuenode1/value /property property nameyarn.nodemanager.aux-services/name valuemapreduce_shuffle/value /property property nameyarn.nodemanager.resource.memory-mb/name value3072/value /property /configurationaux-services忘了配的典型现象是MapReduce 任务能启动Map 阶段跑完 100% 之后卡死不动最后超时失败。原因就是 Shuffle 阶段没有服务接手任务在等一个永远不来的数据。resource.memory-mb建议设成节点内存的 75% 左右2 核 4G 的从节点填 3072 比较稳填满 4096 会让系统本身没有余量NodeManager 端起不来。最后是workers文件2.x 里叫slaves写上三个从节点的主机名每行一个。这个文件决定了start-dfs.sh会去哪些机器拉 DataNode 进程写成 IP 或者写错主机名都会导致启动脚本静默跳过那台机器。3.4 格式化与启动wordcount 是唯一的验收标准配置文件分发到四台机器之后第一次启动前必须格式化 NameNode而且只能格式化一次# 只在 node1 执行且只在首次搭建时执行 hdfs namenode -format # 启动 HDFS 与 YARN脚本在 node1 上执行即可 start-dfs.sh start-yarn.sh # 四台机器分别执行确认进程齐全 jpsjps的输出是判断集群健康最直接的方式。node1 上应该看到 NameNode、SecondaryNameNode、ResourceManager从节点上应该看到 DataNode 和 NodeManager。少哪个进程就去对应的日志目录里翻logs/*.log通常前二十行就能看到原因。格式化的坑值得单独说如果集群跑起来之后因为配置错误又格式化了一次NameNode 会生成新的 clusterID而 DataNode 的 VERSION 文件里还是旧的结果是 DataNode 启动后立刻退出日志里写着Incompatible clusterIDs。解决办法是把所有节点的 data 目录清空再重新格式化而不是反复执行-format。最后用 wordcount 做端到端验收。这一步同时验证了 HDFS 读写、YARN 调度和 MapReduce 执行三条链路# 创建输入目录把配置文件本身当输入数据 hadoop fs -mkdir -p /input hadoop fs -put $HADOOP_HOME/etc/hadoop/*.xml /input # 提交 wordcount 作业 hadoop jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-*.jar \ wordcount /input /output # 查看结果应能看到 xml 标签被统计出来 hadoop fs -cat /output/part-r-00000 | head -20作业跑完的时间取决于机器规格四节点 2 核 4G 的配置下通常两三分钟。如果卡在map 0% reduce 0%超过五分钟先去 8088 端口看作业状态再去 NodeManager 日志里找容器启动失败的原因八成是内存参数给太小或者 Shuffle 服务没配。输出目录/output必须是不存在的重复提交同一个路径会直接报FileAlreadyExistsException换个名字或者先hadoop fs -rm -r /output。4. 打通对象存储Hadoop 与 Spark 读写 OBS 的接法与参数Hadoop 集群自己跑通只是第一步实验报告里的重头戏是让计算层直接读写对象存储。这一层做不通后面所有的 Spark 和交互式查询都是空谈。4.1 走 s3a 还是走厂商连接器差异与选择云上的对象存储大多兼容 S3 协议Hadoop 生态里对应的实现叫s3a它是 Apache 官方维护的随 Hadoop 一起发布不需要额外装东西。另一种做法是用云厂商提供的对象存储连接器通常是一个 jar 包放进$HADOOP_HOME/share/hadoop/common/lib下即可。两者的差别在细节上。s3a的优势是通用、随版本走、文档全缺点是它对文件系统的语义模拟有限重命名操作本质上是复制加删除处理大量小文件时性能很差。厂商连接器一般会针对自家存储做优化比如支持更高效的重命名、更好的并发控制但版本和 Hadoop 版本强绑定升级 Hadoop 时经常要跟着换包。我的建议是实验和课程作业用s3a因为不用折腾 jar 包依赖如果后续要做正经的数据管道再评估厂商连接器。判断标准很简单——如果你发现 Spark 写数据时commit阶段耗时占比超过一半那就是重命名开销的问题该换连接器了。不管走哪条路都需要在core-site.xml里补一组访问配置configuration property namefs.s3a.endpoint/name valueobs.lt;regiongt;.example-cloud.com/value /property property namefs.s3a.access.key/name value${env.OBS_AK}/value /property property namefs.s3a.secret.key/name value${env.OBS_SK}/value /property property namefs.s3a.path.style.access/name valuetrue/value /property property namefs.s3a.connection.ssl.enabled/name valuetrue/value /property /configurationendpoint填内网端点path.style.access设成 true 是因为部分对象存储不支持虚拟主机风格的访问设成 false 会报域名解析失败。AK/SK 用${env.XXX}的形式引用环境变量避免明文落在配置文件里——如果某台机器的环境变量没配启动时会直接报找不到变量比默默用一个错的密钥要好排查。4.2 连通性测试从 put 到 get 走一遍配置改完先做最小验证不要直接上 Spark 作业。用hadoop fs命令访问对象存储路径是最快的探针# 列出桶内内容这一步验证 endpoint 与密钥是否正确 hadoop fs -ls s3a://bdp-lab-2024/ # 上传一个本地文件验证写权限 hadoop fs -put /opt/module/hadoop-2.7.7/etc/hadoop/core-site.xml \ s3a://bdp-lab-2024/test/core-site.xml # 读回来验证下载链路 hadoop fs -cat s3a://bdp-lab-2024/test/core-site.xml | head -5三条命令分别对应三个失败面-ls失败通常是 endpoint 或桶名写错报UnknownHostException或者 404-put失败是密钥权限不足报 403-cat失败一般是网络策略问题。分步验证的好处是错误信息指向明确比在一个 Spark 作业里看到一堆堆栈要好处理得多。执行前记得在每台机器上source一下环境变量文件。只在 node1 上配了 AK/SK从节点跑任务时就会报认证失败而这个错误在 YARN 的容器日志里往往被埋在几十行 WARN 之后。4.3 性能与计费上的现实约束对象存储和 HDFS 的模型完全不同这一点直接决定了作业怎么设计。HDFS 是块存储追加和重命名是元数据操作对象存储是键值对重命名等于复制整个对象再删掉原对象。这个差异带来的直接影响是Spark 或 MapReduce 写输出时_temporary目录到最终目录的提交阶段会非常慢输出文件越多越慢。所以第一个约束是控制输出文件数量。用repartition或者coalesce把结果压到几十个文件以内比生成几千个小文件再想办法合并要划算。第二个约束是不要把对象存储当 HDFS 用中间结果还是落在 HDFS 的本地盘上只在最终输出和跨作业共享数据时用对象存储。计费上要留意的点同区域内网访问不计流量费这个是大前提跨区域访问按流量计费请求次数也计费大量小文件的 GET/PUT 请求数量会很可观。实验阶段数据量小感觉不到一旦数据规模上去把几千个几 KB 的文件怼进桶里请求费用可能比存储费用还高。提示判断是否走了内网看fs.s3a.endpoint的域名用的是内网还是公网地址。用错了不会报错只是慢而且账单上会体现出来。5. 避坑排查四节点集群最容易翻车的五处这一章是从实际搭建过程里攒出来的每一条都对应一个具体现象、一个根因和一个可操作的解决办法。排查顺序建议按现象匹配不要按顺序试。5.1 免密登录昨天还好今天就要密码现象集群跑了一晚上第二天start-dfs.sh卡在某台机器上要求输入密码输入后又提示Permission denied。原因.ssh目录或密钥文件权限被修改。常见触发是scp -r分发目录时把权限带过去了或者有人为了方便把私钥改成 644。解决四台机器统一执行chmod 700 ~/.ssh chmod 600 ~/.ssh/id_rsa chmod 644 ~/.ssh/id_rsa.pub然后用ssh -vvv node2看详细握手过程输出里会明确写出哪个文件的权限被拒绝。改完权限重新试一次不需要重新生成密钥。5.2 DataNode 启动后立刻退出日志写 clusterID 不匹配现象start-dfs.sh执行完node1 上只有 NameNode从节点的 DataNode 起不来jps看不到进程。原因NameNode 被格式化过不止一次新生成的 clusterID 和 DataNode 本地 VERSION 文件里的旧 ID 对不上。解决不要反复格式化。先停掉所有进程删除所有节点上的dfs.datanode.data.dir和dfs.namenode.name.dir目录内容然后只在 node1 上执行一次hdfs namenode -format再统一启动。如果集群里已经有数据格式化前必须确认数据可以丢这一步没有后悔药。5.3 集群看似正常但任务提交后容器全部失败现象wordcount 作业提交后map 0%卡住8088 页面上看到所有容器都是 FAILEDNodeManager 日志里有大量Container exited with a non-zero exit code 1。原因NodeManager 分配的内存超过节点实际可用量容器启动时被系统 OOM killer 杀掉或者yarn.nodemanager.aux-services没配Shuffle 服务没起来。解决先把yarn.nodemanager.resource.memory-mb降到节点内存的 75% 以下同时把mapreduce.map.memory.mb和mapreduce.reduce.memory.mb显式设小一点。再确认aux-services的值是mapreduce_shuffle改完同步到四台机器并重启 YARN。5.4 访问对象存储报 403但密钥明明是对的现象hadoop fs -ls s3a://bucket/报AccessDenied控制台上看密钥状态正常。原因三种可能——密钥所属的账号没有该桶的读权限endpoint 用了另一个区域的地址机器时间偏差超过签名有效期允许的范围。解决先确认桶的权限策略里给了这个账号读权限再核对 endpoint 的区域与桶的区域一致最后用date看四台机器的时间偏差大于五分钟就同步一下。签名机制对时间敏感机器时间漂移是这类 403 里最隐蔽的一种。5.5 Spark 提交到 YARN 报找不到主类或 jar 包现象spark-submit --master yarn提交后立刻失败日志里是ClassNotFoundException或者Failed to locate the jar。原因集群模式cluster下 driver 跑在 NodeManager 上本地路径的 jar 在那边不存在或者HADOOP_CONF_DIR没设Spark 找不到 YARN 的配置。解决用--master yarn --deploy-mode client先跑通确认逻辑没问题再切 cluster 模式切 cluster 时把依赖用--jars明确列出或者打成 fat jar。同时在spark-env.sh里显式设置HADOOP_CONF_DIR指向 Hadoop 配置目录四台机器保持一致。6. 交互式查询进阶Spark SQL 直查 OBS 数据与结果校验前面几章搭起来的东西最终要落到能查这件事上。实验报告里的大数据交互式查询环节本质就是让 Spark SQL 直接对着对象存储里的数据建外表然后用 SQL 把结果算出来。这一步跑通整份实验的价值才算闭环。做法上先确认 Spark 能读到 OBS 的配置。把第 4 章的core-site.xml内容合并进$SPARK_HOME/conf下或者用--files在提交时带上然后启动spark-sql# 启动交互式 SQL带上对象存储配置 spark-sql --master yarn \ --conf spark.hadoop.fs.s3a.endpointobs.region.example-cloud.com \ --conf spark.hadoop.fs.s3a.access.key$OBS_AK \ --conf spark.hadoop.fs.s3a.secret.key$OBS_SK进去之后建外表。关键点是LOCATION指向对象存储路径且表类型用 EXTERNAL删表不会删数据CREATE EXTERNAL TABLE access_log ( dt STRING, uid STRING, url STRING, status INT ) ROW FORMAT DELIMITED FIELDS TERMINATED BY , STORED AS TEXTFILE LOCATION s3a://bdp-lab-2024/warehouse/access_log/; -- 先看分区/文件是否被正确识别 SELECT count(*) FROM access_log; -- 按状态码聚合验证计算链路 SELECT status, count(*) AS cnt FROM access_log GROUP BY status ORDER BY cnt DESC LIMIT 10;字段类型要和实际文件对齐CSV 里如果带引号或者有表头count(*)会把表头也算进去数字看着多一行。STORED AS TEXTFILE适合实验数据真实场景下改成 Parquet 或 ORC列式存储能让聚合查询快一个数量级而且对象存储上的读取量会小很多。验证结果是否可信我的习惯是做一次交叉校验用hadoop fs -cat把原始文件取下来用awk数一遍某个状态码的行数再和 SQL 结果对一下。对不上就去看EXPLAIN输出重点看PartitionFilters和PushedFilters有没有生效——如果过滤条件没有下推Spark 会把整个目录的数据拉回来再过滤数据量一大就表现为查询很慢但结果是对的。还有一个容易忽略的技巧把查询结果写回对象存储时加一个DISTRIBUTE BY或者手动repartition控制输出文件数。我一般会按结果规模估算每 128MB 一个文件比较合适太小就是大量小文件太大则单任务压力过高。写完用hadoop fs -ls数一下文件个数超过预期就说明分区策略有问题。从那以后我每次做完这类实验都会先用一条count(*)和一次-cat交叉验证再去写复杂的聚合逻辑——顺序反了后面所有结论都建立在一个可能读错的数据集上。希望帮到你。本文还有配套的精品资源点击获取