简介:本资源是一份面向高校计算机专业学生与大数据初学者的Hadoop实践教学文档,聚焦教育数据场景下的分布式成绩分析系统设计与实现。文档完整覆盖Hadoop完全分布式集群搭建(含VMware虚拟化、CentOS 6.8部署、Hadoop配置)、MapReduce编程实战(计算各科平均分/最高分/最低分、课程均分排序、相同分数频次统计等核心分析逻辑),以及调试排错与运行结果验证,兼具理论说明与工程落地细节。资源为单文件Word文档(.docx),共1个文件,大小1.46MB,内容结构清晰,含项目背景、需求分析、开发工具、集群搭建七步详解、编码实现四大模块、测试总结及参考文献,适合作为课程设计报告范本或Hadoop入门实操指南。目前已有1502人学习下载,可直接用于教学参考、实验复现或毕业设计技术支撑。
1. 这不是PPT演示稿,而是一套能跑通的Hadoop成绩分析实战链:从三台虚拟机到MapReduce输出真实统计结果
你手头这份《基于Hadoop的成绩分析系统.docx》,不是课程设计交差用的Word模板,而是一份可落地、可复现、带完整集群拓扑和MapReduce源码的工程级实操笔记。它解决的不是“Hadoop是什么”这种概念题,而是“CentOS 6.8下怎么让三台虚拟机真正组成HDFS+YARN集群”“MapReduce代码里为什么reduce端拿不到全部分数迭代器”“为什么jps能看到DataNode但50070页面打不开”这类一线部署时卡住半天的真实问题。整套流程围绕高校真实学生成绩场景展开——不是造轮子,是处理kechengscore.txt里每行“课程名\t分数”的原始数据,输出每门课的平均分、最高/最低分、按均分排序、甚至统计“92分在Java课出现了几次”这种细粒度指标。它面向两类人:一是刚学完Hadoop理论、急需一个有血有肉的分布式作业闭环来建立手感的学生;二是需要快速搭建教学演示环境、又不想被Hadoop 2.6.4与CentOS 6.8兼容性坑死的实训导师。别被标题里的“.docx”迷惑——这文档里藏着的,是VMware克隆配置、hosts硬编码、NTP时间同步脚本、SSH免密登录的三次Enter键确认、以及一段能直接编译进Eclipse并提交到YARN的Java MapReduce代码。接下来,我们就把它从纸面拆解成终端里一行行可执行的命令、可调试的逻辑、可验证的结果。
2. Hadoop完全分布式集群搭建:从VMware克隆到NameNode格式化的七步闭环
2.1 VMware虚拟机拓扑设计:为什么必须是1主3从且IP段严格限定
这不是随意分配的虚拟机数量。Hadoop 2.6.4的完全分布式模式要求明确的角色分离:master节点承担NameNode(HDFS元数据管理)、ResourceManager(YARN资源调度);slave1~slave3则作为DataNode(数据存储)和NodeManager(任务执行)。若只建单节点伪分布,后续MapReduce作业无法体现真正的并行分片能力,也压根测不出“某门课92分出现次数”这类聚合逻辑在多节点间的Shuffle行为。IP地址规划更是关键——文档中强制设定为192.168.128.x网段,原因有三:第一,VMware NAT模式默认子网是192.168.x.0,手动改为192.168.128.0才能确保虚拟机与宿主机网络互通;第二,Hadoop配置文件(如core-site.xml)里fs.defaultFS参数写死hdfs://master:9000,而master这个主机名必须通过/etc/hosts解析到192.168.128.130,任何IP变动都会导致Connection refused;第三,NTP时间同步依赖该网段广播,若slave节点IP不在192.168.128.0/24内,ntpdate master会超时失败,进而引发HDFS启动时“Clock skew detected”的致命错误。所以,克隆前务必确认:master初始IP为.130,slave1为.131,slave2为.132,slave3为.133,且四台机的/etc/sysconfig/network-scripts/ifcfg-eth0中IPADDR、NETMASK、GATEWAY三者严格匹配NAT设置。
# 在master上执行,验证网络连通性(必须全部ping通) ping -c 3 192.168.128.130 # 自身 ping -c 3 192.168.128.131 # slave1 ping -c 3 192.168.128.132 # slave2 ping -c 3 192.168.128.133 # slave3提示:若ping不通,先检查VMware虚拟网络编辑器中的NAT设置是否已将子网IP改为
192.168.128.0,网关为192.168.128.2,DHCP范围为.128-.254;再确认每台虚拟机的ifcfg-eth0中ONBOOT=yes且BOOTPROTO=static。
2.2 CentOS 6.8基础环境加固:关闭防火墙、禁用SELinux、配置本地YUM源
CentOS 6.8默认开启iptables防火墙和SELinux安全模块,这两者是Hadoop集群启动失败的头号杀手。iptables会拦截DataNode向NameNode的心跳端口(9000)、NodeManager向ResourceManager的通信端口(8030-8033),导致jps显示进程但Web UI空白;SELinux则会阻止Hadoop进程读写/usr/local/hadoop目录,报错Permission denied。文档中service iptables stop & chkconfig iptables off仅是临时方案,必须追加永久禁用:
# 彻底关闭iptables(CentOS 6.8) sudo service iptables stop sudo chkconfig iptables off # 永久禁用SELinux(修改配置文件后需重启) sudo sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config # 验证是否生效(重启前可临时设为permissive) sudo setenforce 0YUM源配置同样致命。文档要求将CentOS-Base.repo等文件重命名为.bak,再编辑CentOS-Media.repo启用本地ISO镜像源,这是为了解决CentOS 6.8官方源已停止维护、yum install必然失败的问题。但操作中极易遗漏关键步骤:挂载ISO后必须执行yum clean all清除旧缓存,否则仍会尝试连接失效的网络源。正确流程如下:
# 1. 挂载ISO(假设ISO路径为/media/CentOS-6.8-x86_64-minimal.iso) sudo mkdir -p /media/cdrom sudo mount /dev/sr0 /media/cdrom # 2. 编辑CentOS-Media.repo,确保enabled=1且baseurl=file:///media/cdrom sudo vi /etc/yum.repos.d/CentOS-Media.repo # 修改后内容应包含: # [c6-media] # name=CentOS-$releasever - Media # baseurl=file:///media/cdrom/ # gpgcheck=1 # enabled=1 # 3. 清理缓存并生成新元数据 sudo yum clean all sudo yum makecache # 4. 安装必要工具(注意:文档中命令有笔误,正确为yum install -y vim-enhanced zip openssh-server openssh-clients) sudo yum install -y vim-enhanced zip openssh-server openssh-clients2.3 JDK 1.7与Hadoop 2.6.4的深度绑定:环境变量、权限、版本校验三重锁
Hadoop 2.6.4官方明确要求JDK 1.7(非1.8+),因为其内部大量使用javax.xml.bind等在JDK 9+中被移除的API。文档中Windows端安装JDK 7u80、Linux端安装jdk-7u80-linux-x64.rpm是精准匹配。但环境变量配置常被忽略两个细节:第一,JAVA_HOME必须指向JDK安装根目录(如/usr/java/jdk1.7.0_80),而非/usr/java/jdk1.7.0_80/jre;第二,Hadoop的hadoop-env.sh中export JAVA_HOME必须与系统级/etc/profile中一致,否则start-dfs.sh会报Error: JAVA_HOME is not set。更隐蔽的坑是权限——RPM包安装后,/usr/java/jdk1.7.0_80目录属主为root,若Hadoop以普通用户(如hadoop)运行,会因无权读取rt.jar而崩溃。解决方案是统一用root用户部署,并在hadoop-env.sh中显式声明:
# 在/etc/profile末尾添加(所有节点执行) export JAVA_HOME=/usr/java/jdk1.7.0_80 export PATH=$JAVA_HOME/bin:$PATH source /etc/profile # 验证JDK(所有节点) java -version # 应输出 java version "1.7.0_80" # 在/usr/local/hadoop-2.6.4/etc/hadoop/hadoop-env.sh中修改 export JAVA_HOME=/usr/java/jdk1.7.0_80 export HADOOP_OPTS="-Djava.net.preferIPv4Stack=true"注意:
HADOOP_OPTS中-Djava.net.preferIPv4Stack=true是关键!CentOS 6.8默认启用IPv6,Hadoop组件间通信若走IPv6会导致UnknownHostException,此参数强制使用IPv4。
2.4 SSH免密登录与NTP时间同步:分布式协同的底层信任链
Hadoop集群启动本质是master节点通过SSH向所有slave节点下发start-dfs.sh等脚本。若每次都要输密码,自动化即告破产。文档中ssh-keygen -t rsa后三次Enter生成无密钥对是标准操作,但ssh-copy-id命令常因目标节点sshd未启用公钥认证而失败。必须手动检查slave节点的/etc/ssh/sshd_config:
# 在所有slave节点执行 sudo vi /etc/ssh/sshd_config # 确保以下三行未被注释且值正确: PubkeyAuthentication yes AuthorizedKeysFile .ssh/authorized_keys PasswordAuthentication no # 生产环境建议关闭密码登录 sudo service sshd restartNTP时间同步则是HDFS的隐形命脉。Hadoop要求集群内节点时间偏差≤10秒,否则DataNode注册会被NameNode拒绝,日志报java.io.IOException: Failed on local exception: java.io.IOException: Response is null。文档中master配置restrict 192.168.128.0 mask 255.255.255.0 nomodify notrap是精髓——它允许整个192.168.128.0/24网段的slave向master同步时间,同时禁止外部修改。但实操中常犯的错是:在slave上执行ntpdate master后未启动ntpd服务,导致下次重启时间又漂移。正确姿势是:
# master节点(启动NTP服务并设开机自启) sudo yum install -y ntp sudo service ntpd start sudo chkconfig ntpd on # slave节点(先同步一次,再启动服务持续校准) sudo yum install -y ntp sudo ntpdate master sudo service ntpd start sudo chkconfig ntpd on2.5 HDFS格式化与集群启停:namenode初始化、进程校验、Web UI访问链路
./hdfs namenode -format不是简单命令,而是HDFS的“创世操作”——它在hadoop.tmp.dir(默认/usr/local/hadoop-2.6.4/tmp)下生成namesecondary、dfs/name等关键目录,并写入初始fsimage镜像。若此前未清空/usr/local/hadoop-2.6.4/tmp,格式化会失败并报Directory is not empty。因此,首次格式化前必做:
# 在master节点执行(所有节点需提前创建hadoop用户及目录) sudo rm -rf /usr/local/hadoop-2.6.4/tmp sudo mkdir -p /usr/local/hadoop-2.6.4/tmp sudo chown -R root:root /usr/local/hadoop-2.6.4启动集群后,jps是第一道检验关。文档图17显示master有NameNode、ResourceManager、SecondaryNameNode,slave有DataNode、NodeManager,但实际部署中常见“少进程”现象。根本原因在于slaves文件配置错误——该文件必须位于$HADOOP_HOME/etc/hadoop/slaves,且每行一个slave主机名(如slave1),不能写IP或带空格。若slaves文件为空或路径错误,start-dfs.sh只会启动master本地进程。
# 验证slaves文件(master节点) cat $HADOOP_HOME/etc/hadoop/slaves # 正确输出应为: # slave1 # slave2 # slave3 # 启动集群(master节点) cd $HADOOP_HOME sbin/start-dfs.sh sbin/start-yarn.sh sbin/mr-jobhistory-daemon.sh start historyserver # 文档中误写为mr-jobhistory-demo.sh # 检查进程(master) jps | grep -E "(NameNode|ResourceManager|SecondaryNameNode)" # 检查进程(slave1) jps | grep -E "(DataNode|NodeManager)"Web UI访问链路需打通三层:第一层是Hadoop服务端口开放(50070、8088、19888),第二层是宿主机hosts文件映射(C:\Windows\System32\drivers\etc\hosts添加192.168.128.130 master),第三层是浏览器直连http://master:50070。若页面空白,先telnet测试端口:telnet 192.168.128.130 50070,若不通则检查iptables是否真关闭;若通但页面白屏,则查看$HADOOP_HOME/logs/hadoop-root-namenode-master.log,常见BindException: Address already in use说明端口被占用。
3. MapReduce成绩分析实现:从文本解析到多维度聚合的代码级拆解
3.1 输入数据规范与HDFS上传:kechengscore.txt的字段约束与分隔符陷阱
文档中初始数据kechengscore.txt格式为“课程名\t分数”,看似简单,但MapReduce对输入格式极其敏感。若文件含中文乱码(如UTF-8 BOM头)、行尾混用\r\n与\n、或课程名中含制表符\t,Mapper的split("\t")会直接劈裂数据,导致ArrayIndexOutOfBoundsException。必须在上传前清洗:
# 在Linux下检查文件编码与换行符 file -i kechengscore.txt # 应显示 charset=utf-8 unix2dos -n kechengscore.txt kechengscore_clean.txt # 统一为LF换行 # 手动删除BOM(若存在) sed -i '1s/^\xEF\xBB\xBF//' kechengscore_clean.txt # 上传至HDFS(master节点) hadoop fs -mkdir -p /input/score hadoop fs -put kechengscore_clean.txt /input/score/ hadoop fs -ls /input/score/ # 验证上传成功提示:
hadoop fs -cat /input/score/kechengscore_clean.txt | head -5可实时查看HDFS中文件前5行,确认无乱码。
3.2 计算每门课平均/最高/最低分:Mapper分组逻辑与Reducer聚合算法
文档中maxminaverage134.java的Mapper输出<课程名, 分数>,Reducer接收<课程名, Iterable<分数>>进行聚合。但原始代码存在性能隐患:它将所有分数存入ArrayList再调用Collections.max(),当某门课有10万学生时,内存溢出风险极高。工业级写法应边迭代边计算极值:
// 改进版Reducer(替换原文averageReducer) public static class averageReducer extends Reducer<Text, LongWritable, Text, Text> { @Override protected void reduce(Text key, Iterable<LongWritable> values, Context context) throws IOException, InterruptedException { long sum = 0; long count = 0; long max = Long.MIN_VALUE; long min = Long.MAX_VALUE; for (LongWritable val : values) { long score = val.get(); sum += score; count++; if (score > max) max = score; if (score < min) min = score; } double avg = (double) sum / count; String result = String.format("Avg:%.2f, Max:%d, Min:%d", avg, max, min); context.write(key, new Text(result)); } }关键参数说明:context.write(key, new Text(result))中key是课程名(Text类型),result是拼接字符串(Text类型)。String.format保证小数点后两位,避免科学计数法。此写法时间复杂度O(n),空间复杂度O(1),彻底规避大列表内存压力。
3.3 按课程平均分降序输出:二次排序与MapReduce链式作业设计
文档需求“将每门课程的平均成绩从高到低输出”,但Hadoop默认按key字典序排序,而课程名(如“数学”“英语”)字典序≠均分序。必须引入二次排序:Mapper输出<均分倒序值_课程名, 1>,利用Hadoop对Text key的字典序特性,使95.50_数学排在87.20_英语之前。但均分是double,需转为固定长度字符串避免95.5排在95.50前:
// Mapper中计算均分后生成复合key(需先计算全局均分,此处简化为单次作业) // 实际生产中应分两步:第一步求各课均分,第二步用均分作key排序 // 为简化教学,此处用“均分*100取整+课程名”构造key int avgInt = (int) Math.round(avg * 100); // 如95.50→9550 String compositeKey = String.format("%05d_%s", 10000 - avgInt, course); // 倒序:9550→04450 context.write(new Text(compositeKey), new Text(course + "\t" + String.format("%.2f", avg)));更健壮的方案是使用链式MapReduce:第一个Job输出<课程名, 均分>到HDFS,第二个Job读取该结果,Mapper不做处理,Reducer按均分排序后输出。这虽增加I/O,但逻辑清晰、易于调试。
3.4 统计相同分数出现次数:Map端Combiner预聚合与Counters计数器
需求“求每门课中相同分数出现次数”,本质是<课程名_分数, 1>的计数。若直接让Reducer处理所有<课程名_分数>,数据量巨大。应启用Combiner在Map端预聚合:
// Mapper输出<课程名_分数, 1> String mapKey = course + "_" + score; context.write(new Text(mapKey), new LongWritable(1)); // Combiner(与Reducer逻辑相同) public static class ScoreCountCombiner extends Reducer<Text, LongWritable, Text, LongWritable> { @Override protected void reduce(Text key, Iterable<LongWritable> values, Context context) throws IOException, InterruptedException { long sum = 0; for (LongWritable val : values) sum += val.get(); context.write(key, new LongWritable(sum)); } } // 在Job配置中启用 job.setCombinerClass(ScoreCountCombiner.class);此外,可用Hadoop Counters统计总记录数、异常记录数,辅助验证数据质量:
// Mapper中 context.getCounter("SCORE_COUNTER", "TOTAL_RECORDS").increment(1); if (score < 0 || score > 100) { context.getCounter("SCORE_COUNTER", "INVALID_SCORE").increment(1); }运行后通过hadoop job -counter <job_id> SCORE_COUNTER TOTAL_RECORDS查看总数,确保无脏数据。
3.5 Eclipse集成Hadoop插件:从dropins加载到Map/Reduce视图配置
文档中hadoop-eclipse-plugin-2.6.0.jar放入dropins目录是正确路径,但Eclipse Mars及以后版本需额外配置:
- 启动Eclipse时添加JVM参数
-Dorg.eclipse.swt.browser.DefaultType=webkit,否则Map/Reduce视图白屏; Window → Preferences → Hadoop Map/Reduce中设置Hadoop installation directory为/usr/local/hadoop-2.6.4;Map/Reduce Locations中添加新Location,Location name填hadoop-cluster,Map/Reduce Master填master:9001(非8021,因mapred-site.xml中mapreduce.jobtracker.address设为master:9001),DFS Master填master:9000。
注意:若Eclipse报
ClassNotFoundException: org.apache.hadoop.fs.FileSystem,说明未导入Hadoop依赖JAR。需右键项目→Properties → Java Build Path → Libraries → Add External JARs,添加$HADOOP_HOME/share/hadoop/common/*.jar等目录下所有JAR。
4. 避坑指南:Hadoop 2.6.4 + CentOS 6.8集群部署与MapReduce运行的五大血泪经验
4.1 现象:jps显示NameNode进程,但http://master:50070页面空白,日志报java.net.BindException: Address already in use
原因:NameNode默认端口9000被其他进程(如MySQL、Redis)占用,或上次异常退出后/usr/local/hadoop-2.6.4/tmp/dfs/name/current/VERSION文件残留导致端口绑定失败。
解决:先lsof -i :9000查占用进程并kill;再rm -rf /usr/local/hadoop-2.6.4/tmp/dfs/name/current/*清空NameNode数据目录,重新执行hdfs namenode -format。
4.2 现象:start-dfs.sh后slave节点jps无DataNode,hadoop fs -ls /报Call From slave1 to master:9000 failed on connection exception
原因:/etc/hosts中master主机名解析错误,或slave节点core-site.xml中fs.defaultFS值写成hdfs://192.168.128.130:9000(IP)而非hdfs://master:9000(主机名),导致反向DNS解析失败。
解决:在所有slave节点执行ping master,若不通则检查/etc/hosts;确认$HADOOP_HOME/etc/hadoop/core-site.xml中<value>hdfs://master:9000</value>,且master在/etc/hosts中映射到192.168.128.130。
4.3 现象:MapReduce作业提交后卡在ACCEPTED状态,YARN Web UI(8088端口)显示Application未分配Container
原因:YARN的yarn.nodemanager.resource.memory-mb(默认8192MB)超过slave物理内存,或yarn.scheduler.minimum-allocation-mb(默认1024MB)设置过大,导致NodeManager无法满足Container内存请求。
解决:在所有slave节点的yarn-site.xml中调整:
<property> <name>yarn.nodemanager.resource.memory-mb</name> <value>4096</value> <!-- 设为物理内存一半 --> </property> <property> <name>yarn.scheduler.minimum-allocation-mb</name> <value>512</value> <!-- 降低最小分配 --> </property>重启YARN:sbin/stop-yarn.sh && sbin/start-yarn.sh。
4.4 现象:Eclipse中Run on Hadoop成功,但HDFS输出目录为空,hadoop fs -ls /output报No such file or directory
原因:MapReduce程序中FileOutputFormat.setOutputPath(job, new Path(args[1]))的args[1]传入的是相对路径(如output),Hadoop将其解释为HDFS根目录下的/output,但若该目录已存在,作业会因FileAlreadyExistsException失败且静默退出。
解决:在Job提交前添加自动清理逻辑:
// 在main方法中 FileSystem fs = FileSystem.get(conf); Path outputPath = new Path(args[1]); if (fs.exists(outputPath)) { fs.delete(outputPath, true); // 强制删除 } FileOutputFormat.setOutputPath(job, outputPath);4.5 现象:kechengscore.txt含中文课程名(如“高等数学”),MapReduce输出结果中课程名显示为é«˜çæ•°å¦¦乱码
原因:Hadoop默认使用UTF-8编码,但CentOS 6.8终端locale为zh_CN.UTF-8,而Eclipse或Xshell未正确设置字符集,导致Mapper读取文件时解码错误。
解决:在Mapper的setup()方法中强制指定编码:
@Override protected void setup(Context context) throws IOException, InterruptedException { // 强制以UTF-8读取输入流 super.setup(context); } // 并在Mapper的map()中,若用BufferedReader读文件,需指定编码: // BufferedReader reader = new BufferedReader(new InputStreamReader(fs.open(path), "UTF-8"));更彻底方案:在core-site.xml中添加<property><name>hadoop.native.lib</name><value>false</value></property>禁用本地库,避免编码转换冲突。
5. 进阶验证与生产化技巧:用Shell脚本自动化集群健康检查与结果校验
5.1 编写集群健康检查脚本:一键诊断四大核心指标
手工执行jps、hadoop dfsadmin -report太低效。我习惯用一个check_hadoop.sh脚本覆盖所有关键点,它不依赖Hadoop命令,纯用Linux原生命令验证:
#!/bin/bash # check_hadoop.sh - Hadoop集群健康检查脚本(保存为/usr/local/bin/check_hadoop.sh) echo "=== Hadoop Cluster Health Check ===" echo # 1. 检查网络连通性(master到所有slave) echo "1. Network Connectivity:" for host in master slave1 slave2 slave3; do if ping -c 1 -W 1 $host &>/dev/null; then echo " ✓ $host reachable" else echo " ✗ $host unreachable" fi done echo # 2. 检查关键端口监听(master) echo "2. Port Listening on master:" for port in 9000 50070 8030 8031 8032 8033 8088; do if ss -tuln | grep ":$port" &>/dev/null; then echo " ✓ Port $port listening" else echo " ✗ Port $port not listening" fi done echo # 3. 检查HDFS状态(需hadoop命令) echo "3. HDFS Status:" if hadoop dfsadmin -report 2>/dev/null | grep -q "Live datanodes"; then live=$(hadoop dfsadmin -report 2>/dev/null | grep "Live datanodes" | awk '{print $3}') dead=$(hadoop dfsadmin -report 2>/dev/null | grep "Dead datanodes" | awk '{print $3}') echo " ✓ Live DataNodes: $live, Dead: $dead" else echo " ✗ HDFS not accessible" fi echo # 4. 检查YARN应用状态 echo "4. YARN Applications:" if yarn application -list 2>/dev/null | grep -q "application_"; then running=$(yarn application -list 2>/dev/null | grep "RUNNING" | wc -l) finished=$(yarn application -list 2>/dev/null | grep "FINISHED" | wc -l) echo " ✓ Running: $running, Finished: $finished" else echo " ✗ YARN not accessible" fi echo echo "=== Check Complete ==="赋予执行权限并加入crontab每日检查:
chmod +x /usr/local/bin/check_hadoop.sh # 每天凌晨2点执行 echo "0 2 * * * /usr/local/bin/check_hadoop.sh >> /var/log/hadoop_health.log 2>&1" | sudo crontab -5.2 成绩分析结果交叉验证:用Linux命令行快速比对MapReduce输出与原始数据
MapReduce结果可信吗?最笨却最有效的方法是用awk、sort、uniq在原始数据上做相同计算,与HDFS输出对比。例如验证“Java课平均分”:
# 从HDFS获取MapReduce输出 hadoop fs -cat /output/part-r-00000 | grep "Java" | cut -d',' -f1 | sed 's/Avg://' | xargs printf "%.2f\n" # 用awk在原始文件上计算(假设kechengscore.txt在本地) awk -F'\t' '$1=="Java" {sum+=$2; count++} END {printf "Java Avg: %.2f\n", sum/count}' kechengscore.txt # 统计“92分在Java课出现次数” hadoop fs -cat /output_same_score/part-r-00000 | grep "Java_92" awk -F'\t' '$1=="Java" && $2==92 {count++} END {print "Java_92 count:", count}' kechengscore.txt若结果一致,说明MapReduce逻辑正确;若不一致,立即检查Mapper的split("\t")是否被空格干扰,或Reducer的累加是否漏了count++。
5.3 生产环境必备:日志归档与磁盘空间监控策略
Hadoop日志($HADOOP_HOME/logs/)默认不轮转,半年后可达数十GB。我在log4j.properties中强制启用滚动:
# 在$HADOOP_HOME/etc/hadoop/log4j.properties末尾添加 log4j.appender.RFA=org.apache.log4j.RollingFileAppender log4j.appender.RFA.File=${hadoop.log.dir}/hadoop-${user.name}-${hadoop.log.file} log4j.appender.RFA.MaxFileSize=256MB log4j.appender.RFA.MaxBackupIndex=20 log4j.appender.RFA.layout=org.apache.log4j.PatternLayout log4j.appender.RFA.layout.ConversionPattern=%d{ISO8601} %p %c: %m%n磁盘空间监控则用df -h结合阈值告警:
# 检查HDFS数据目录(/usr/local/hadoop-2.6.4/tmp/dfs/data) used_percent=$(df /usr/local/hadoop-2.6.4/tmp/dfs/data | tail -1 | awk '{print $5}' | sed 's/%//') if [ $used_percent -gt 85 ]; then echo "ALERT: HDFS data dir usage ${used_percent}%" | mail -s "Hadoop Disk Alert" admin@localhost fi从那以后我每次部署新集群,都强制走一遍check_hadoop.sh脚本,再用awk对原始数据抽样验证三个核心指标。这看似多花10分钟,却避免了后续几小时在日志里大海捞针。希望帮到你。
本文还有配套的精品资源,点击获取