一、为什么需要分布式存储
- 数据量太大,单机存储能力有上限,需要靠数量来解决问题
- 数量的提升带来的是网络传输、磁盘读写、CPU、内存等各方面的综合提升。 分布式组合在一起可以达到1+1>2的效果
二、分布式的基础架构分析
1、分布式的基础架构
大数据体系中,分布式的调度主要有2类架构模式:
- 去中心化模式 - 去中心化模式,没有明确的中心。众多服务器之间基于特定规则进行同步协调。
- 中心化模式
2、主从模式
大数据框架,大多数的基础架构上,都是符合:中心化模式的。
即:有一个中心节点(服务器)来统筹其它服务器的工作,统一指挥,统一调派,避免混乱。
这种模式,也被称之为:一主多从模式,简称主从模式(Master And Slaves)
三、HDFS的基础架构
1、HDFS
HDFS是Hadoop三大组件(HDFS、MapReduce、YARN)之一
- 全称是:Hadoop Distributed File System(Hadoop分布式文件系统)
- 是Hadoop技术栈内提供的分布式数据存储解决方案
- 可以在多台服务器上构建存储集群,存储海量的数据
2、HDFS的基础架构
HDFS集群(分布式存储)
- 主角色:NameNode - HDFS系统的主角色,是一个独立的进程- 负责管理HDFS整个文件系统- 负责管理DataNode
- 从角色:DataNode - HDFS系统的从角色,是一个独立进程- 主要负责数据的存储,即存入数据和取出数据
- 主角色辅助角色:SecondaryNameNode - NameNode的辅助,是一个独立进程- 主要帮助NameNode完成元数据整理工作(打杂)
一个典型的HDFS集群,就是由1个DataNode加若干(至少一个)DataNode组成
四、HDFS集群环境部署
1、VMware虚拟机中部署
1.1、安装包下载
官方网址:https://hadoop.apache.org,课程使用当前最新的发行版:3.3.4版。
1.2、集群规划
在前置准备章节,我们准备了基于VMware的三台虚拟机,其硬件配置如下。
节点
CPU
内存
node1
1核心
4GB
node2
1核心
2GB
node3
1核心
2GB
Hadoop HDFS的角色包含:
- NameNode,主节点管理者
- DataNode,从节点工作者
- SecondaryNameNode,主节点辅助
节点
服务
node1
NameNode、DataNode、SecondaryNameNode
node2
DataNode
node3
DataNode
请确认已经完成前置准备中的服务器创建、固定IP、防火墙关闭、Hadoop用户创建、SSH免密、JDK部署等操作。
以下操作 node1节点执行 以root身份登陆
1. 上传Hadoop安装包到node1节点中
2. 解压缩安装包到/export/server/中
tar -zxvf hadoop-3.3.4.tar.gz -C /export/server
3. 构建软链接
cd /export/server
ln -s /export/server/hadoop-3.3.4 hadoop
4. 进入hadoop安装包内
cd hadoop
Hadoop****安装包目录结构
cd 进入Hadoop安装包内,通过ls -l命令查看文件夹内部结构
各个文件夹含义如下
- bin,存放Hadoop的各类程序(命令)
- etc,存放Hadoop的配置文件
- include,C语言的一些头文件
- lib,存放Linux系统的动态链接库(.so文件)
- libexec,存放配置Hadoop系统的脚本文件(.sh和.cmd)
- licenses-binary,存放许可证文件
- sbin,管理员程序(super bin)
- share,存放二进制源码(Java jar包)
1.3、修改配置文件,应用自定义设置
配置HDFS集群,我们主要涉及到如下文件的修改:
- workers: 配置从节点(DataNode)有哪些
- hadoop-env.sh: 配置Hadoop的相关环境变量
- core-site.xml: Hadoop核心配置文件
- hdfs-site.xml: HDFS核心配置文件
这些文件均存在与$HADOOP_HOME/etc/hadoop文件夹中。
ps:$HADOOP_HOME是后续我们要设置的环境变量,其指代Hadoop安装文件夹即/export/server/hadoop
1.3.1、配置workers文件
填入的node1、node2、node3表明集群记录了三个从节点(DataNode)
# 进入配置文件目录
cd etc/hadoop
# 编辑workers文件
vim workers
# 填入如下内容
node1
node2
node3
1.3.2、配置hadoop-env.sh文件
# 填入如下内容
#JAVA_HOME,指明JDK环境的位置在哪
export JAVA_HOME=/export/server/jdk
#JAVHADOOP_HOME,指明Hadoop安装位置
export HADOOP_HOME=/export/server/hadoop
#HADOOP_CONF_DIR,指明Hadoop配置文件目录位置
export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop
#HADOOP_LOG_DIR,指明Hadoop运行日志目录位置
export HADOOP_LOG_DIR=$HADOOP_HOME/logs
1.3.3、配置core-site.xml文件
在文件内部填入如下内容
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://node1:8020</value>
</property>
<property>
<name>io.file.buffer.size</name>
<value>131072</value>
</property>
</configuration>
key:fs.defaultFS
含义:HDFS文件系统的网络通讯路径
值:hdfs://node1:8020
协议为hdfs://
namenode为node1
namenode通讯端口为8020
key:io.file.buffer.size
含义:io操作文件缓冲区大小
值:131072 bit
hdfs://node1:8020为整个HDFS内部的通讯地址,应用协议为hdfs://(Hadoop内置协议) 表明DataNode将和node1的8020端口通讯,node1是NameNode所在机器 此配置固定了node1必须启动NameNode进程
1.3.4、配置hdfs-site.xml文件
# 在文件内部填入如下内容
<configuration>
<property>
<name>dfs.datanode.data.dir.perm</name>
<value>700</value>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>/data/nn</value>
</property>
<property>
<name>dfs.namenode.hosts</name>
<value>node1,node2,node3</value>
</property>
<property>
<name>dfs.blocksize</name>
<value>268435456</value>
</property>
<property>
<name>dfs.namenode.handler.count</name>
<value>100</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>/data/dn</value>
</property>
</configuration>
针对hdfs-site.xml,简单分析一下配置文件的内容
# 在文件内部填入如下内容
<configuration> key:dfs.datanode.data.dir.perm
<property>
<name>dfs.datanode.data.dir.perm</name> 含义:hdfs文件系统,默认创建的文件权限设置
<value>700</value> 值:700,即:rwx------
</property>
<property>
<name>dfs.namenode.name.dir</name> key:dfs.namenode.name.dir
<value>/data/nn</value> 含义:NameNode元数据的存储位置
</property> 值:/data/nn,在node1节点的/data/nn目录下
<property> key:dfs.namenode.hosts
<name>dfs.namenode.hosts</name> 含义:NameNode允许哪几个节点的DataNode连接(即允许加入集群)
<value>node1,node2,node3</value> 值:node1、node2、node3,这三台服务器被授权
</property>
<property>
<name>dfs.blocksize</name> key:dfs.blocksize
<value>268435456</value> 含义:hdfs默认块大小
</property> 值:268435456(256MB)
<property>
<name>dfs.namenode.handler.count</name> key:dfs.namenode.handler.count
<value>100</value> 含义:namenode处理的并发线程数
</property> 值:100,以100个并行度处理文件系统的管理任务
<property>
<name>dfs.datanode.data.dir</name> key:dfs.datanode.data.dir
<value>/data/dn</value> 含义:从节点DataNode的数据存储目录
</property> 值:/data/dn,即数据存放在node1、node2、node3,三台机器的/data/dn内
</configuration>
- namenode数据存放node1的/data/nn
- datanode数据存放node1、node2、node3的/data/dn
所以应该
在node1节点:
mkdir -p /data/nn
mkdir /data/dn
在node2和node3节点:
mkdir -p /data/dn
1.3.5、分发Hadoop****文件夹
目前,已经基本完成Hadoop的配置操作,可以从node1将hadoop安装文件夹远程复制到node2、node3
# 在node1执行如下命令
cd /export/server
scp -r hadoop-3.3.4 node2:`pwd`/
scp -r hadoop-3.3.4 node3:`pwd`/
# 在node2执行,为hadoop配置软链接
# 在node2执行如下命令
ln -s /export/server/hadoop-3.3.4 /export/server/hadoop
# 在node3执行,为hadoop配置软链接
# 在node3执行如下命令
ln -s /export/server/hadoop-3.3.4 /export/server/hadoop
1.3.6、配置环境变量
为了方便我们操作Hadoop,可以将Hadoop的一些脚本、程序配置到PATH中,方便后续使用。
在Hadoop文件夹中的bin、sbin两个文件夹内有许多的脚本和程序,现在来配置一下环境变量
- vim /etc/profile
# 在/etc/profile文件底部追加如下内容
export HADOOP_HOME=/export/server/hadoop
export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
- 在node2和node3配置同样的环境变量
1.3.7、授权为hadoop****用户
hadoop部署的准备工作基本完成
为了确保安全,hadoop系统不以root用户启动,我们以普通用户hadoop来启动整个Hadoop服务以root****身份,在node1、node2、node3三台服务器上均执行如下命令
# 以root身份,在三台服务器上均执行
chown -R hadoop:hadoop /data
chown -R hadoop:hadoop /export
1.3.8、 格式化整个文件系统
前期准备全部完成,现在对整个文件系统执行初始化
格式化namenode
# 确保以hadoop用户执行
su - hadoop
# 格式化namenode
hadoop namenode -format
启动
# 一键启动hdfs集群
start-dfs.sh
# 一键关闭hdfs集群
stop-dfs.sh
# 如果遇到命令未找到的错误,表明环境变量未配置好,可以以绝对路径执行
/export/server/hadoop/sbin/start-dfs.sh
/export/server/hadoop/sbin/stop-dfs.sh
1.3.9、查看HDFS WEBUI
启动完成后,可以在浏览器打开:
http://node1:9870,即可查看到hdfs文件系统的管理网页。
五、HDFS的Shell操作
1.、进程启停管理
1.1、一键启停脚本
Hadoop HDFS组件内置了HDFS集群的一键启停脚本。
$HADOOP_HOME/sbin/start-dfs.sh,一键启动HDFS集群
执行原理:
- 在执行此脚本的机器上,启动SecondaryNameNode
- 读取core-site.xml内容(fs.defaultFS项),确认NameNode所在机器,启动NameNode
- 读取workers内容,确认DataNode所在机器,启动全部DataNode
$HADOOP_HOME/sbin/stop-dfs.sh,一键关闭HDFS集群
执行原理:
- 在执行此脚本的机器上,关闭SecondaryNameNode
- 读取core-site.xml内容(fs.defaultFS项),确认NameNode所在机器,关闭NameNode
- 读取workers内容,确认DataNode所在机器,关闭全部NameNode
1.2、单进程启停
除了一键启停外,也可以单独控制进程的启停。
- $HADOOP_HOME/sbin/hadoop-daemon.sh,此脚本可以单独控制所在机器的进程的启停
用法:hadoop-daemon.sh (start|status|stop) (namenode|secondarynamenode|datanode)
- $HADOOP_HOME/bin/hdfs,此程序也可以用以单独控制所在机器的进程的启停
用法:hdfs --daemon (start|status|stop) (namenode|secondarynamenode|datanode)
2、文件系统操作命令
1.1、HDFS****文件系统基本信息
HDFS作为分布式存储的文件系统,有其对数据的路径表达方式。
HDFS同Linux系统一样,均是以/作为根目录的组织形式
- Linux: /usr/local/hello.txt
- HDFS: /usr/local/hello.txt
如何区分呢?
- Linux:file:///
- HDFS:hdfs://namenode:port/
如上路径:
Linux:file:///usr/local/hello.txt
HDFS:hdfs://node1:8020/usr/local/hello.txt
协议头file:/// 或 hdfs://node1:8020/可以省略
需要提供Linux路径的参数,会自动识别为file://
需要提供HDFS路径的参数,会自动识别为hdfs://
3、介绍
关于HDFS文件系统的操作命令,Hadoop提供了2套命令体系
hadoop命令(老版本用法),用法:hadoop fs [generic options]
hdfs命令(新版本用法),用法:hdfs dfs [generic options]
1、创建文件夹
hadoop fs -mkdir [-p] <path> ...
hdfs dfs -mkdir [-p] <path> ...
path 为待创建的目录
-p选项的行为与Linux mkdir -p一致,它会沿着路径创建父目录。
hadoop fs -mkdir -p /itcast/bigdata
hdfs fs -mkdir -p /itheima/hadoop
2、查看指定目录下内容
hadoop fs -ls [-h] [-R] [<path> ...]
hdfs dfs -ls [-h] [-R] [<path> ...]
path 指定目录路径
-h 人性化显示文件size
-R 递归查看指定目录及其子目录
3、上传文件到HDFS****指定目录下
hadoop fs -put [-f] [-p] <localsrc> ... <dst>
hdfs dfs -put [-f] [-p] <localsrc> ... <dst>
-f 覆盖目标文件(已存在下)
-p 保留访问和修改时间,所有权和权限。
localsrc 本地文件系统(客户端所在机器)
dst 目标文件系统(HDFS)
hadoop fs -put words.txt /itcast
hdfs dfs -put file:///etc/profile hdfs://node1:8020/itcast
4、查看HDFS****文件内容
hadoop fs -cat <src> ...
hdfs dfs -cat <src> ...
读取指定文件全部内容,显示在标准输出控制台。
hadoop fs -cat /itcast/words.txt
hdfs dfs -cat /itcast/profile
读取大文件可以使用管道符配合more
hadoop fs -cat <src> | more
hdfs dfs -cat <src> | more
5、下载HDFS****文件
hadoop fs -get [-f] [-p] <src> ... <localdst>
hdfs dfs -get [-f] [-p] <src> ... <localdst>
下载文件到本地文件系统指定目录,localdst必须是目录
-f 覆盖目标文件(已存在下)
-p 保留访问和修改时间,所有权和权限。
6、拷贝HDFS****文件
hadoop fs -cp [-f] <src> ... <dst>
hdfs dfs -cp [-f] <src> ... <dst>
7、追加数据到HDFS****文件中
hadoop fs -appendToFile <localsrc> ... <dst>
hdfs dfs -appendToFile <localsrc> ... <dst>
将所有给定本地文件的内容追加到给定dst文件。
dst如果文件不存在,将创建该文件。
如果<localSrc>为-,则输入为从标准输入中读取。
8、HDFS****数据移动操作
hadoop fs -mv <src> ... <dst>
hdfs dfs -mv <src> ... <dst>
移动文件到指定文件夹下
可以使用该命令移动数据,重命名文件的名称
9、HDFS****数据删除操作
hadoop fs -rm -r [-skipTrash] URI [URI ...]
hdfs dfs -rm -r [-skipTrash] URI [URI ...]
删除指定路径的文件或文件夹
-skipTrash 跳过回收站,直接删除
回收站功能默认关闭,如果要开启需要在core-site.xml内配置:
<property>
<name>fs.trash.interval</name>
<value>1440</value>
</property>
<property>
<name>fs.trash.checkpoint.interval</name>
<value>120</value>
</property>
命令官方指导文档
https://hadoop.apache.org/docs/r3.3.4/hadoop-project-dist/hadoop-common/FileSystemShell.html
HDFS WEB****浏览
除了使用命令操作HDFS文件系统外,在HDFS的WEB UI上也可以查看HDFS文件系统的内容。
使用WEB浏览操作文件系统,一般会遇到权限问题
这是因为WEB浏览器中是以匿名用户(dr.who)登陆的,其只有只读权限,多数操作是做不了的。
如果需要以特权用户在浏览器中进行操作,需要配置如下内容到core-site.xml并重启集群
<property>
<name>hadoop.http.staticuser.user</name>
<value>hadoop</value>
</property>
但是,不推荐这样做
- HDFS WEBUI,只读权限挺好的,简单浏览即可
- 如果给与高权限,会有很大的安全问题,造成数据泄露或丢失
4、HDFS客户端 - Jetbrians产品插件
Big Data Tools****插件
在Jetbrains的产品中,均可以安装插件,其中:Big Data Tools插件可以帮助我们方便的操作HDFS,比如
- IntelliJ IDEA(Java IDE)
- PyCharm(Python IDE)
- DataGrip(SQL IDE)
如图,在设置->Plugins(插件)-> Marketplace(市场),搜索Big Data Tools,点击Install安装即可
配置****Windows
需要对Windows系统做一些基础设置,配合插件使用
- 解压Hadoop安装包到Windows系统,如解压到:E:\hadoop-3.3.4
- 设置$HADOOP_HOME环境变量指向:E:\hadoop-3.3.4
- 下载- hadoop.dll(https://github.com/steveloughran/winutils/blob/master/hadoop-3.0.0/bin/hadoop.dll)- winutils.exe(https://github.com/steveloughran/winutils/blob/master/hadoop-3.0.0/bin/winutils.exe)
- 将hadoop.dll和winutils.exe放入$HADOOP_HOME/bin中
配置Big Data Tools插件
打开插件
或者如图指定Windows上解压的Hadoop安装文件夹的etc/hadoop目录也可以
会自动读取配置文件连接上HDFS
六、HDFS的存储原理
1、存储原理
- 数据存入HDFS是分布式存储,即每一个服务器节点,负责数据的一部分。
- 数据在HDFS上是划分为一个个Block块进行存储。
2、fsck命令
**HDFS副本块数量的配置 **
在前面我们了解了HDFS文件系统的数据安全,是依靠多个副本来确保的。
如何设置默认文件上传到HDFS中拥有的副本数量呢?可以在hdfs-site.xml中配置如下属性:
<property>
<name>dfs.replication</name>
<value>3</value>
</property>
这个属性默认是3,一般情况下,我们无需主动配置(除非需要设置非3的数值)
如果需要自定义这个属性,请修改每一台服务器的hdfs-site.xml文件,并设置此属性。
除了配置文件外,我们还可以在上传文件的时候,临时决定被上传文件以多少个副本存储。
hadoop fs -D dfs.replication=2 -put test.txt /tmp/
如上命令,就可以在上传test.txt的时候,临时设置其副本数为2
对于已经存在HDFS的文件,修改dfs.replication属性不会生效,如果要修改已存在文件可以通过命令
hadoop fs -setrep [-R] 2 path
如上命令,指定path的内容将会被修改为2个副本存储。
-R选项可选,使用-R表示对子目录也生效。
fsck****命令检查文件的副本数
同时,我们可以使用hdfs提供的fsck命令来检查文件的副本数
hdfs fsck path [-files [-blocks [-locations]]]
fsck可以检查指定路径是否正常
-files可以列出路径内的文件状态
-files -blocks 输出文件块报告(有几个块,多少副本)
-files -blocks -locations 输出每一个block的详情
block****配置
可以看到通过fsck命令我们验证了:
文件有多个副本
文件被分成多个块存储在hdfs
对于块(block),hdfs默认设置为256MB一个,也就是1GB文件会被划分为4个block存储。
块大小可以通过参数:
<property>
<name>dfs.blocksize</name>
<value>268435456</value>
<description>设置HDFS块大小,单位是b</description>
</property>
3、NameNode元数据
edits****文件
NameNode基于一批edits和一个fsimage文件的配合完成整个文件系统的管理和维护
edits文件,是一个流水账文件,记录了hdfs中的每一次操作,以及本次操作影响的文件其对应的block
fsimage****文件
将全部的edits文件,合并为最终结果,即可得到一个FSImage文件
NameNode****元数据管理维护
NameNode基于edits和FSImage的配合,完成整个文件系统文件的管理。
- 每次对HDFS的操作,均被edits文件记录
- edits达到大小上线后,开启新的edits记录
- 定期进行edits的合并操作
如当前没有fsimage文件, 将全部edits合并为第一个fsimage
如当前已存在fsimage文件,将全部edits和已存在的fsimage进行合并,形成新的fsimage
元数据合并控制参数
对于元数据的合并,是一个定时过程,基于:
dfs.namenode.checkpoint.period,默认3600(秒)即1小时
dfs.namenode.checkpoint.txns,默认1000000,即100W次事务
只要有一个达到条件就执行。
检查是否达到条件,默认60秒检查一次,基于:
dfs.namenode.checkpoint.check.period,默认60(秒),来决定
SecondaryNameNode****的作用
SecondaryNameNode会通过http从NameNode拉取数据(edits和fsimage)
然后合并完成后提供给NameNode使用。
4、HDFS数据的读写流程
数据写入流程
- 客户端向NameNode发起请求
- NameNode审核权限、剩余空间后,满足条件允许写入,并告知客户端写入的DataNode地址
- 客户端向指定的DataNode发送数据包
- 被写入数据的DataNode同时完成数据副本的复制工作,将其接收的数据分发给其它DataNode
- 如上图,DataNode1复制给DataNode2,然后基于DataNode2复制给Datanode3和DataNode4
- 写入完成客户端通知NameNode,NameNode做元数据记录工作
关键信息点:
NameNode不负责数据写入,只负责元数据记录和权限审批
客户端直接向1台DataNode写数据,这个DataNode一般是离客户端最近(网络距离)的那一个
数据块副本的复制工作,由DataNode之间自行完成(构建一个PipLine,按顺序复制分发,如图1给2, 2给3和4)
数据读取流程
1、客户端向NameNode申请读取某文件
2、 NameNode判断客户端权限等细节后,允许读取,并返回此文件的block列表
3、客户端拿到block列表后自行寻找DataNode读取即可
关键点:
1、数据同样不通过NameNode提供
2、NameNode提供的block列表,会基于网络距离计算尽量提供离客户端最近的
这是因为1个block有3份,会尽量找离客户端最近的那一份让其读取
版权归原作者 半间烟雨 所有, 如有侵权,请联系我们删除。