ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Hadoop分布式存储系统实战:从伪分布式到完全分布式集群搭建与源码文档

Hadoop分布式存储系统实战:从伪分布式到完全分布式集群搭建与源码文档 简介这是一套基于Hadoop的分布式存储系统完整项目源码面向计算机、人工智能、通信工程等专业的在校学生、教师及企业开发者可用于毕业设计、课程设计、作业提交或项目初期立项演示。资源包共203个文件约94.33MB以87个jar依赖库、32个class编译文件、16个java源码、18个jsp页面、18个css样式、15个xml配置及1个war部署包为主另含md说明文档与少量图片资源覆盖从后端逻辑到前端展示的完整结构。项目代码均经过测试运行成功答辩评审平均分达96分已有136人学习关注。读者可获取可直接运行的分布式存储实现方案理解Hadoop环境下文件存储、控制台交互与注册登录等模块的代码组织方式并借助README与文档说明快速上手在现有基础上修改扩展功能适合小白进阶学习与二次开发参考。1. 从一台机器到一套存储Hadoop 分布式存储系统到底在解决什么单机磁盘塞满的那一刻大多数人才会认真考虑分布式存储。我最早接触这套东西是因为一台跑日志采集的机器硬盘连续爆了两周运维每天删文件续命。后来换成 Hadoop 的 HDFS 打底数据按块切分、多副本散落到不同节点单盘故障不再等于数据丢失扩容也从「换大盘」变成「加节点」。这个标题里的「基于 Hadoop 的分布式存储系统」本质就是拿 HDFS 做底层存储配一套能跑起来的集群再补上源码和文档让它成为一个可交付、可复现的工程而不是一份只能看的课程设计。它适合两类人一类是要交课程设计、需要完整源码和说明文档的学生另一类是想在自己机器或几台旧服务器上搭一套能用的分布式存储、顺便理解 HDFS 读写链路的工程师。下面按「先跑通伪分布式、再扩到完全分布式、最后看源码和文档怎么落地」的顺序讲参数和坑都会给到。2. 伪分布式先跑通Hadoop 安装与配置的最小闭环2.1 为什么先搭伪分布式而不是直接上集群完全分布式搭建听起来更「正式」但对第一次接触 Hadoop 的人来说直接上多节点会把网络、免密、时间同步、防火墙这些问题一次性堆到你面前出错时根本分不清是配置写错还是环境没通。伪分布式把 NameNode、DataNode、ResourceManager、NodeManager 全塞在一台机器上用不同进程模拟多角色配置项和完全分布式几乎一致只是主机名都指向 localhost。常见做法是先在 Ubuntu 上用伪分布式把 HDFS 读写、YARN 提交任务跑通确认配置文件、环境变量、Java 版本都没问题再把这套配置复制到多台机器上改主机名。这样排错范围小血泪经验是伪分布式都起不来的配置搬到集群上只会更乱。2.2 环境准备与 JDK 安装的具体命令Hadoop 3.x 依赖 JDK 8 或 JDK 11我一般用 JDK 8兼容性最稳。先确认系统版本和内存伪分布式建议至少 4GB 内存、20GB 空闲磁盘。下面是在 Ubuntu 上的准备步骤命令都带注释。# 更新包索引并安装常用工具 sudo apt update sudo apt install -y ssh rsync vim curl # 安装 JDK 8Hadoop 3 对 JDK 8 支持最成熟 sudo apt install -y openjdk-8-jdk # 验证 Java 版本输出应包含 1.8 java -version # 配置 SSH 免密伪分布式也需要本机免密登录 ssh-keygen -t rsa -P -f ~/.ssh/id_rsa cat ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys # 测试免密登录本机第一次会提示 yes/no ssh localhost逻辑说明SSH 免密是 Hadoop 启动脚本用 ssh 拉起远程进程的前提伪分布式虽然在本机但脚本仍然走 ssh 通道不配免密会卡在输入密码。参数说明-P 表示空密码方便脚本调用chmod 600保证私钥权限权限过松 ssh 会拒绝使用。JDK 路径后面要写进hadoop-env.sh先用readlink -f $(which java)拿到真实路径去掉末尾的/bin/java就是JAVA_HOME。2.3 下载解压与四个核心配置文件的改法从 Hadoop 官网下载二进制包解压到/usr/local或用户目录。下面以 3.3.x 系列为例具体小版本按官网当前稳定版选不要用太老的 2.xYARN 和 HDFS 的默认端口、配置项差异较大。# 解压到 /usr/local目录名简化 sudo tar -zxvf hadoop-3.3.6.tar.gz -C /usr/local/ sudo mv /usr/local/hadoop-3.3.6 /usr/local/hadoop sudo chown -R $USER:$USER /usr/local/hadoop # 配置环境变量追加到 ~/.bashrc echo export HADOOP_HOME/usr/local/hadoop ~/.bashrc echo export PATH$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin ~/.bashrc echo export JAVA_HOME/usr/lib/jvm/java-8-openjdk-amd64 ~/.bashrc source ~/.bashrc接下来改四个文件都在$HADOOP_HOME/etc/hadoop/下。hadoop-env.sh里把export JAVA_HOME改成上面确认的路径core-site.xml配默认文件系统和临时目录hdfs-site.xml配副本数和 NameNode、DataNode 数据目录mapred-site.xml和yarn-site.xml配计算框架。关键片段如下。!-- core-site.xml -- configuration property namefs.defaultFS/name valuehdfs://localhost:9000/value /property property namehadoop.tmp.dir/name value/usr/local/hadoop/tmp/value /property /configuration !-- hdfs-site.xml伪分布式副本数必须为 1 -- configuration property namedfs.replication/name value1/value /property property namedfs.namenode.name.dir/name value/usr/local/hadoop/data/namenode/value /property property namedfs.datanode.data.dir/name value/usr/local/hadoop/data/datanode/value /property /configuration逻辑说明fs.defaultFS告诉客户端默认连哪个 NameNode端口 9000 是常见约定改了要同步改后面所有命令。dfs.replication在伪分布式下只能设 1设 3 会因为只有一个 DataNode 而一直报副本不足。hadoop.tmp.dir是很多临时文件的根单独指到一个目录方便清理。参数说明dfs.namenode.name.dir和dfs.datanode.data.dir建议放在数据盘而不是系统盘后面扩集群时这个习惯能省事。2.4 格式化与启动验证 HDFS 真的能读写配置改完先格式化 NameNode再启动。格式化只能做一次重复格式化会导致 DataNode 的 clusterID 和 NameNode 不一致这是新手最常翻车的地方。# 格式化 NameNode只做一次 hdfs namenode -format # 启动 HDFS 和 YARN start-dfs.sh start-yarn.sh # 查看进程应有 NameNode、DataNode、ResourceManager、NodeManager jps # 在 HDFS 上建目录并上传文件 hdfs dfs -mkdir -p /user/$USER/input echo hello hadoop distributed storage test.txt hdfs dfs -put test.txt /user/$USER/input/ # 读回来验证 hdfs dfs -cat /user/$USER/input/test.txt逻辑说明jps是判断进程是否起来的直接手段缺哪个进程就去对应日志里找原因日志在$HADOOP_HOME/logs/。hdfs dfs -put走的是客户端到 NameNode 再到 DataNode 的完整写入链路能读回来说明存储链路通了。参数说明-mkdir -p递归建目录-put本地文件到 HDFS路径默认相对/user/当前用户。如果jps里没有 DataNode先看hadoop.tmp.dir目录权限再看是否重复格式化过。3. 从伪分布式扩到完全分布式集群搭建的关键参数3.1 多节点规划与主机名、hosts 的统一伪分布式跑通后扩到完全分布式主要是把「localhost」换成真实主机名并让所有节点互相认识。我一般用三台机器一台 master 兼 NameNode 和 ResourceManager两台 slave 做 DataNode 和 NodeManager。规划表如下主机名和 IP 按自己环境改。角色主机名说明NameNode / ResourceManagermaster主节点负责元数据和资源调度DataNode / NodeManagerslave1从节点存数据块、跑容器DataNode / NodeManagerslave2从节点存数据块、跑容器每台机器上改/etc/hostname和/etc/hosts把三台的主机名和 IP 都写进去。这一步不做后面start-dfs.sh会因为解析不到主机名而失败。时间同步也要做用ntpdate或chrony让三台时间差在秒级以内否则 YARN 的心跳判断会出玄学问题。3.2 免密登录与配置文件的分发master 要能免密 ssh 到两台 slaveslave 之间按需。做法是把 master 的公钥追加到所有节点的authorized_keys。# 在 master 上生成密钥如果还没有 ssh-keygen -t rsa -P -f ~/.ssh/id_rsa # 分发公钥到 slave1 和 slave2 ssh-copy-id slave1 ssh-copy-id slave2 # 验证 ssh slave1 hostname ssh slave2 hostname逻辑说明ssh-copy-id把公钥写到目标机的authorized_keys之后 master 上的启动脚本才能无密码拉起 slave 上的进程。参数说明如果目标机 ssh 端口不是 22用-p指定。分发完配置后把 master 上改好的$HADOOP_HOME整个目录用scp -r或rsync同步到两台 slave保证配置一致。这一步偷懒手动改后面一定会因为某个文件不一致而排查半天。3.3 workers 文件与副本数的调整完全分布式下workers文件旧版本叫slaves列出所有 DataNode 主机名每行一个。hdfs-site.xml里dfs.replication改成 3让每个块在三台机器上各存一份这样挂一台不丢数据。# 编辑 workers 文件 vim $HADOOP_HOME/etc/hadoop/workers # 内容 # slave1 # slave2逻辑说明workers文件被start-dfs.sh和start-yarn.sh读取决定去哪些机器拉起 DataNode 和 NodeManager。参数说明dfs.replication设 3 是常见默认如果只有两台 DataNode设 3 会一直有副本处于欠复制状态按实际节点数设不要超过 DataNode 数量。改完配置在 master 上重新格式化并启动然后jps逐台确认进程。3.4 用 hdfs dfsadmin 看集群真实状态集群起来后不要只看jps要用管理命令看块和节点状态。# 查看集群概览关注 Live datanodes 数量 hdfs dfsadmin -report # 查看安全模式状态刚启动可能短暂处于安全模式 hdfs dfsadmin -safemode get # 上传一个大一点的文件观察副本分布 hdfs dfs -put bigfile.txt /user/$USER/input/ hdfs fsck /user/$USER/input/bigfile.txt -files -blocks -locations逻辑说明-report给出每个 DataNode 的容量、已用、剩余是判断集群是否健康的第一入口。-safemode get返回 OFF 才说明可以正常写。fsck能看到每个块落在哪些节点上验证副本数是否真的达到 3。参数说明-files -blocks -locations三个选项一起用输出最全。如果Live datanodes少于预期去对应 slave 的日志里找 DataNode 启动失败原因常见的是数据目录权限或 clusterID 不一致。4. 源码与文档说明怎么落地从能跑到能交付4.1 源码目录该包含哪些内容标题里带「源代码文档说明」意味着交付物不只是能跑的集群还要有可读的代码和说明。一套完整的 Hadoop 分布式存储系统源码通常包含几部分HDFS 客户端操作封装上传、下载、删除、列目录、基于 MapReduce 或 Spark 的示例计算任务、配置文件模板、启动停止脚本。下面是一个 HDFS 客户端封装的 Java 示例用官方FileSystemAPI适合放进课程设计或工程脚手架。import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import java.net.URI; public class HdfsClient { public static void main(String[] args) throws Exception { // 指定 NameNode 地址与 core-site.xml 中 fs.defaultFS 一致 Configuration conf new Configuration(); conf.set(fs.defaultFS, hdfs://master:9000); // 用当前用户身份连接避免权限拒绝 FileSystem fs FileSystem.get(new URI(hdfs://master:9000), conf, hadoop); // 上传本地文件到 HDFS fs.copyFromLocalFile(new Path(/home/hadoop/test.txt), new Path(/user/hadoop/input/test.txt)); // 判断文件是否存在并打印长度 Path remote new Path(/user/hadoop/input/test.txt); if (fs.exists(remote)) { System.out.println(file length: fs.getFileStatus(remote).getLen()); } fs.close(); } }逻辑说明FileSystem.get是客户端入口传入 URI 和用户身份。copyFromLocalFile内部走的是「先写 DataNode 管道、再向 NameNode 汇报」的完整流程。参数说明第三个参数hadoop是连接用户集群开了权限检查时这个用户要有对应目录的写权限否则报Permission denied。编译时把 Hadoop 的 jar 加进 classpath用hadoop classpath拿到完整依赖路径。4.2 文档说明要写清楚的三件事文档说明不是把命令抄一遍而是要让人照着能复现。我一般要求文档至少覆盖三块环境要求系统版本、JDK 版本、内存磁盘下限、配置项清单每个改动的文件、改哪一行、为什么改、验证步骤跑什么命令、期望输出是什么。配置项清单用表格最清楚下面是一个示例片段。文件配置项值作用core-site.xmlfs.defaultFShdfs://master:9000指定默认文件系统hdfs-site.xmldfs.replication3数据块副本数yarn-site.xmlyarn.nodemanager.aux-servicesmapreduce_shuffleYARN 运行 MapReduce 必需mapred-site.xmlmapreduce.framework.nameyarn计算框架指向 YARN逻辑说明文档里写「为什么改」比写「改成什么」更重要因为读者环境不同值可能要调但原因不变。参数说明yarn.nodemanager.aux-services不配mapreduce_shuffleMapReduce 任务会卡在 shuffle 阶段这是完全分布式下最常见的配置遗漏之一。4.3 用脚本把启动停止标准化交付物里最好带启动停止脚本避免每次手敲一堆命令。一个简单的cluster.sh如下。#!/bin/bash # 集群启停脚本在 master 上执行 case $1 in start) start-dfs.sh start-yarn.sh ;; stop) stop-yarn.sh stop-dfs.sh ;; status) jps hdfs dfsadmin -report | head -20 ;; *) echo usage: $0 {start|stop|status} ;; esac逻辑说明停止顺序先 YARN 后 HDFS避免 YARN 还在跑任务时 HDFS 先停导致任务失败。参数说明status里用head -20截取报告前 20 行快速看节点数量完整报告还是用hdfs dfsadmin -report。脚本要给执行权限chmod x cluster.sh。5. 避坑与排查Hadoop 集群最常见的五类翻车5.1 重复格式化导致 DataNode 起不来现象jps里只有 NameNode 没有 DataNodeDataNode 日志报clusterID不一致或Incompatible clusterIDs。原因NameNode 格式化会生成新的 clusterID而 DataNode 数据目录里还是旧的两者对不上。解决停掉所有进程删掉 NameNode 和 DataNode 的数据目录dfs.namenode.name.dir和dfs.datanode.data.dir指向的目录重新hdfs namenode -format再启动。记住格式化只做一次之后重启不要带-format。5.2 端口占用或防火墙拦截现象NameNode 启动报BindException: Address already in use或客户端连不上 9000 端口。原因9000、8088、9870 等端口被其他进程占用或防火墙没放行。解决用netstat -tlnp | grep 9000找到占用进程改 Hadoop 端口或停掉冲突进程跨节点访问要在防火墙放行对应端口或在内网环境临时关闭防火墙测试。注意生产环境不要直接关防火墙按端口放行。5.3 副本数设得比 DataNode 多现象hdfs dfsadmin -report里一直有Under-replicated blocks写文件慢或报副本不足。原因dfs.replication设成 3但只有 1 或 2 个 DataNode 在线。解决把副本数改成不超过在线 DataNode 数量伪分布式设 1两台设 2三台及以上设 3。改完用hdfs dfs -setrep -w 2 /path对已有文件调整副本数。5.4 权限拒绝与用户身份混乱现象客户端报Permission denied: userxxx, accessWRITE。原因HDFS 上的目录属主和客户端连接用户不一致或集群开了权限检查。解决用hdfs dfs -ls /user看目录属主用hdfs dfs -chown改属主或在客户端代码里显式指定有权限的用户。伪分布式下常见的是用 root 建了目录之后用普通用户连写不进去。5.5 时间不同步引发的心跳异常现象NodeManager 频繁掉线又上线YARN 任务莫名失败。原因节点间时间差过大心跳和超时判断错乱。解决所有节点装chrony或ntp指向同一时间源用timedatectl确认同步状态。这个坑很隐蔽日志里不一定直接写「时间不同步」但心跳包重传、任务重试往往和它有关。6. 进阶用 Docker 快速复现与源码阅读的切入点如果你不想在物理机上折腾环境用 Docker 跑 Hadoop 是个省事的验证方式。官方和社区都有 Hadoop 镜像常见做法是拉一个带伪分布式的镜像映射端口后直接进容器操作。下面是一个基于 Dockerfile 的最小构建思路把配置和启动脚本固化进去。# 拉取一个 Hadoop 基础镜像按自己环境选可用镜像 docker pull sequenceiq/hadoop-docker:2.7.1 # 启动容器并映射 NameNode、YARN 端口 docker run -it -p 50070:50070 -p 8088:8088 \ --name hadoop-test sequenceiq/hadoop-docker:2.7.1 /etc/bootstrap.sh -bash # 进容器后验证 hdfs dfs -ls /逻辑说明镜像里已经配好伪分布式进容器就能用适合快速验证客户端代码和命令。参数说明-p映射 Web UI 端口50070 是旧版 NameNode UI 端口3.x 是 9870按镜像版本调整。注意镜像版本和你要验证的 API 版本要对得上2.x 和 3.x 的部分客户端 API 有差异。源码阅读的切入点我一般从org.apache.hadoop.hdfs包下的DFSClient和DistributedFileSystem开始前者是客户端写数据的核心后者是FileSystem在 HDFS 上的实现。读的时候配合hdfs dfs -put的实际行为对照看一个文件从本地到 DataNode 管道的过程比干读代码快得多。验证方法上可以自己写一个断点观察DFSOutputStream如何分包、如何选 DataNode、如何处理管道中某个节点失败后的重试。这套链路理解了HDFS 的很多配置项为什么存在就自然清楚了。我自己踩得最深的一次是在一台内存只有 2GB 的机器上硬跑完全分布式NameNode 和 ResourceManager 抢内存进程反复被系统杀掉日志里只看到Killed查了半天才反应过来是内存不够。后来养成习惯搭之前先算内存NameNode 和 ResourceManager 各留 1GB 以上DataNode 和 NodeManager 按数据量留宁可少开节点也不要让主节点饿死。希望帮到你。本文还有配套的精品资源点击获取
返回列表