一 分布式文件存储
了解为什么海量数据需要使用分布式存储技术
100T数据太大,单台服务器无法承担。于是:
分布式服务器集群
靠数量取胜,多台服务器组合,才能Hold住,如下
分布式不仅仅是解决了能存的问题, 多台服务器协同工作带来的也是性能的横向扩展。
- 三倍的网络传输效率
- 三倍的磁盘写入效率
为什么需要分布式存储?
- 数据量太大,单机存储能力有上限,需要靠数量来解决问题
- 数量的提升带来的是网络传输、磁盘读写、CPU、内存等各方面的综合提升。 分布式组合在一起可以达到1+1>2的效果
二 分布式基础结构分析
数量多,在现实生活中往往带来的不是提升,而是:混乱。
大家思考一下, 众多的服务器一起工作,是如何高效、不出问题呢?
大数据体系中,分布式的调度主要有2类架构模式:
- 去中心化模式
- 中心化模式
去中心化模式
去中心化模式,没有明确的中心。众多服务器之间基于特定规则进行同步协调。
中心化模式
有明确的中心,基于中心节点分配工作
大数据框架,大多数的基础架构,都是符合:中心化模式的。即:有一个中心节点(服务器)来统筹其它服务器的工作,统一指挥,统一调派,避免混乱。
这种模式,也被称之为:一主多从模式,简称主从模式(Master And Slaves);
我们学习的Hadoop框架,就是一个典型的主从模式(中心化模式)架构的技术框架。
三 HDFS基础架构
HDFS,即Hadoop Distributed File System,分布式文件存储系统。HDFS是一个典型的主从模式架构。
3.1 Hadoop与HDFS的关系
HDFS是Hadoop三大组件(HDFS、MapReduce、YARN)之一,可在多台服务器上构建集群,提供分布式数据存储能力
- 全称是:Hadoop Distributed File System(Hadoop分布式文件系统)
- 是Hadoop技术栈内提供的分布式数据存储解决方案
- 可以在多台服务器上构建存储集群,存储海量的数据
3.2 HDFS架构
HDFS集群(分布式存储),包含以下三大角色
- 主角色:NameNode
- 从角色:DataNode
- 主角色辅助角色:SecondaryNameNode
NameNode:
HDFS系统的主角色,是一个独立的进程
负责管理HDFS整个文件系统
负责管理DataNode
DataNode:
HDFS系统的从角色,是一个独立进程
主要负责数据的存储,即存入数据和取出数据
SecondaryNameNode:
NameNode的辅助,是一个独立进程
主要帮助NameNode完成元数据整理工作(打杂)
HDFS分布式文件系统集群
一个典型的HDFS集群,就是由1个NameNode加若干(至少一个)DataNode组成。
四 HDFS集群环境部署
4.1 环境准备
官网下载tar包
在centos虚拟机里部署HDFS集群。官方网址:https://hadoop.apache.org,最新版本是3.3.6,这里使用版本:3.3.4版
点击此处下载tar包
共600多兆,浏览器下载较慢。建议使用第三方下载工具,如迅雷进行下载。
准备虚拟机
准备基于VMware的三台虚拟机,三台虚拟机主机名分别设置为node1, node2, node3
# 三台虚拟机分别执行下边命令,修改各自的主机名# 虚拟机1执行
hostnamectl set-hostname node1
# 虚拟机2执行
hostnamectl set-hostname node2
# 虚拟机3执行
hostnamectl set-hostname node3
在三台虚拟机的/etc/hosts文件中,填入如下内容(3台都要添加),以后直接使用主机名访问即可
192.168.119.129 node1
192.168.119.130 node2
192.168.119.131 node3
为了后期在我们window本地操作方便,在Window系统也修改一下hosts文件如下
192.168.119.129 node1
192.168.119.130 node2
192.168.119.131 node3
后续安装的集群化软件,多数需要远程登录以及远程执行命令,我们可以简单起见,配置三台Linux服务器之间的免密码互相SSH登陆
- 在每一台机器都执行:
ssh-keygen -t rsa -b 4096
,一路回车到底即可 - 在每一台机器都执行:
ssh-copy-id node1ssh-copy-id node2ssh-copy-id node3
- 执行完毕后,node1、node2、node3之间将完成root用户之间的免密互通
以后在node1就能直接登录node2和node3了
# 登录node2虚拟机
ssh node2;
# ........开始操作node2机器# 退出node2机器
exit;
后续大数据的软件,将不会以root用户启动 (确保安全,养成良好的习惯),我们为大数据的软件创建一个单独的用户hadoop,并为三台服务器同样配置hadoop用户的免密互通
- 在每一台机器执行:
useradd hadoop
,创建hadoop用户 - 在每一台机器执行:
passwd hadoop
,设置hadoop用户密码为12345678(至少8位) - 在每一台机器均切换到hadoop用户:
su - hadoop
,并执行ssh-keygen -t rsa -b 4096
,创建ssh密钥 - 在每一台机器均执行
ssh-copy-id node1ssh-copy-id node2ssh-copy-id node3
此外,还需要安装jdk、关闭防火墙、 不会的同学参考这里:linux常用配置
先切换回root用户
su root
mkdir -p /export/server
上传之前下载好的tar包,然后解压
# 进入如下目录
cd /export/server/
解压
tar -zxvf hadoop-3.3.4.tar.gz -C /export/server
构建软链接
cd /export/server
ln -s /export/server/hadoop-3.3.4 hadoop
进入hadoop安装包内
cd hadoop
解压后,目录内的文件及其含义
关闭SELinux
Linux有一个安全模块:SELinux,用以限制用户和程序的相关权限,来确保系统的安全稳定。在当前,我们只需要关闭SELinux功能,避免导致后面的软件运行出现问题即可
在每一台机器执行:
vim /etc/sysconfig/selinux
把第七行的SELINUX值改为disabled(一定写对,不然无法启动系统)
SELINUX=disabled
改完后重启。
时间同步
在三台虚拟机都执行
- 安装ntp软件
yum install -y ntp
- 更新时区
rm -f /etc/localtime;
sudo ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
- 同步时间
ntpdate -u ntp.aliyun.com
- 开启ntp服务并设置开机自启
systemctl start ntpd
systemctl enable ntpd
此时基础环境已经配置完毕,可以给三台虚拟机拍一个快照保存了
4.2 配置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
配置workers文件
# 进入配置文件目录
cd etc/hadoop
# 编辑workers文件
vim workers
# 填入如下内容
node1
node2
node3
填入的node1、node2、node3,是三台机器的主机名,表明集群记录了三个从节点(DataNode)信息。
配置hadoop-env.sh文件
# 填入如下内容
export JAVA_HOME=/export/server/jdk
export HADOOP_HOME=/export/server/hadoop
export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop
export HADOOP_LOG_DIR=$HADOOP_HOME/logs
- JAVA_HOME,指明JDK环境的位置在哪
- HADOOP_HOME,指明Hadoop安装位置
- HADOOP_CONF_DIR,指明Hadoop配置文件目录位置
- HADOOP_LOG_DIR,指明Hadoop运行日志目录位置
通过记录这些环境变量, 来指明上述运行时的重要信息
配置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>
- hdfs://node1:8020为整个HDFS内部的通讯地址,应用协议为hdfs://(Hadoop内置协议)
- 表明DataNode将和node1的8020端口通讯,node1是NameNode所在机器
- 此配置固定了node1必须启动NameNode进程
配置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,简单分析一下配置文件的内容
根据下述2个配置项:
可知:
- namenode数据存放node1的/data/nn,日志存放:/export/server/hadoop/logs
- datanode数据存放node1、node2、node3的/data/dn
所以应该
在node1节点:
mkdir -p /export/server/hadoop/logs
mkdir -p /data/nn
mkdir -p /data/dn
在node2和node3节点:
mkdir -p /data/dn
分发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、node3执行如下命令
ln -s /export/server/hadoop-3.3.4 /export/server/hadoop
为了方便我们操作Hadoop,可以将Hadoop的一些脚本、程序配置到PATH中,方便后续使用
在Hadoop文件夹中的bin、sbin两个文件夹内有许多的脚本和程序,现在来配置一下环境变量(在node2和node3配置同样的环境变量)
vim /etc/profile
# 在/etc/profile文件底部追加如下内容
export HADOOP_HOME=/export/server/hadoop
export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
使配置生效
source /etc/profile
授权为hadoop用户
hadoop部署的准备工作基本完成
为了确保安全,hadoop系统不以root用户启动,我们以普通用户hadoop来启动整个Hadoop服务,所以,现在需要对文件权限进行授权。
ps:请确保已经提前创建好了hadoop用户,并配置好了三台虚拟机hadoop用户之间的免密登录
以root身份,在node1、node2、node3三台服务器上均执行如下命令
# 以root身份,在三台服务器上均执行
chown -R hadoop:hadoop /data
chown -R hadoop:hadoop /export
格式化整个文件系统
前期准备全部完成,现在对整个文件系统执行初始化
格式化namenode(只在node1机器执行即可)
# 确保以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
使用jps
命令查看进程号
如果只有node1有三个进程号,node2、node3没有DataNode进程号,那就需要检查workers文件内没有正确配置;
start-dfs.sh脚本会:
- 在当前机器启动SecondaryNameNode,并根据core-site.xml的记录启动NameNode
- 根据workers文件的记录,启动各个机器的datanode
查看NameNode日志:/export/server/hadoop/logs…;
查看HDFS WEBUI
启动完成后,可以在浏览器打开:http://node1:9870(或者:http://192.168.52.130:9870/),即可查看到hdfs文件系统的管理网页。
datanode节点
五 HDFS的Shell操作
5.1 hdfs启停管理
一键启停脚本
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
单进程启停
除了一键启停外,也可以单独控制进程的启停。
-
$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)
5.2 文件系统操作命令
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://
除非你明确需要写或不写会有BUG,否则一般不用写协议头
关于HDFS文件系统的操作命令,Hadoop提供了2套命令体系
-
hadoop命令(老版本用法),用法:hadoop fs [generic options]
-
hdfs命令(新版本用法),用法:hdfs dfs [generic options]
两者在文件系统操作上,用法完全一致,用哪个都可以。某些特殊操作需要选择hadoop命令或hdfs命令,后边用到的时候具体分析。
创建文件夹
hadoop fs -mkdir [-p] <path> ...
hdfs dfs -mkdir [-p] <path> ...
path 为待创建的目录,-p选项的行为与Linux的 mkdir -p
一致,它会沿着路径创建父目录。
hadoop fs -mkdir -p /maltose/bigdata
hdfs fs -mkdir -p /maltose/hadoop
查看指定目录下内容
hadoop fs -ls [-h] [-R] [<path> ...]
hdfs dfs -ls [-h] [-R] [<path> ...]
path 指定目录路径,-h 人性化显示文件size,-R 递归查看指定目录及其子目录
上传文件到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 /maltose
hdfs dfs -put file:///etc/profile hdfs://node1:8020/maltose
查看HDFS文件内容
hadoop fs -cat <src> ...
hdfs dfs -cat <src> ...
读取指定文件全部内容,显示在标准输出控制台。
hadoop fs -cat /maltose/words.txt
hdfs dfs -cat /maltose/profile
读取大文件可以使用管道符配合more
hadoop fs -cat <src> | more
hdfs dfs -cat <src> | more
下载HDFS文件
hadoop fs -get [-f] [-p] <src> ... <localdst>
hdfs dfs -get [-f] [-p] <src> ... <localdst>
下载文件到本地文件系统指定目录,localdst必须是目录
-f 覆盖目标文件(已存在下)
-p 保留访问和修改时间,所有权和权限。
[root@node1 ~]# mkdir test
[root@node1 ~]# cd test/
[root@node1 test]# ll
total 0
[root@node1 test]# hadoop fs -get /maltose/zookeeper.out ./
[root@node1 test]# ll
total 20
-rw-r--r-- 1 root root 18213 Aug 18 17:54 zookeeper.out
拷贝HDFS文件
hadoop fs -cp [-f] <src> ... <dst>
hdfs dfs -cp [-f] <src> ... <dst>
-f 覆盖目标文件(已存在下)
[root@node3 ~]# hadoop fs -cp /small/1.txt /maltose
[root@node3 ~]# hadoop fs -cp /small/1.txt /maltose/666.txt #重命名
[root@node3 ~]# hadoop fs -ls /maltose
Found 4 items
-rw-r--r-- 3 root supergroup 2 2021-08-18 17:58 /maltose/1.txt
-rw-r--r-- 3 root supergroup 2 2021-08-18 17:59 /maltose/666.txt
追加数据到HDFS文件中
hadoop fs -appendToFile <localsrc> ... <dst>
hdfs dfs -appendToFile <localsrc> ... <dst>
将所有给定本地文件的内容追加到给定dst文件。
dst如果文件不存在,将创建该文件。
如果<localSrc>
为-
,则输入为从标准输入中读取。
#追加内容到文件尾部 appendToFile
[root@node3 ~]# echo 1 >> 1.txt
[root@node3 ~]# echo 2 >> 2.txt
[root@node3 ~]# echo 3 >> 3.txt
[root@node3 ~]# hadoop fs -put 1.txt /
[root@node3 ~]# hadoop fs -cat /1.txt
1
[root@node3 ~]# hadoop fs -appendToFile 2.txt 3.txt /1.txt
[root@node3 ~]# hadoop fs -cat /1.txt
1
2
3
HDFS数据移动操作
hadoop fs -mv <src> ... <dst>
hdfs dfs -mv <src> ... <dst>
移动文件到指定文件夹下
可以使用该命令移动数据,重命名文件的名称
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>
无需重启集群,在哪个机器配置的,在哪个机器执行命令就生效。
回收站默认位置在:/user/用户名(hadoop)/.Trash
HDFS shell其它命令
命令官方指导文档:https://hadoop.apache.org/docs/r3.3.4/hadoop-project-dist/hadoop-common/FileSystemShell.html
5.3 HDFS WEB浏览
除了使用命令操作HDFS文件系统外,在HDFS的WEB UI上也可以查看HDFS文件系统的内容,基本能实现常用的HDFS操作
。
使用WEB浏览操作文件系统,一般会遇到权限问题
这是因为WEB浏览器中是以匿名用户(dr.who)登陆的,其只有只读权限,多数操作是做不了的。如果需要以特权用户在浏览器中进行操作,需要配置如下内容到core-site.xml
并重启集群
<property><name>hadoop.http.staticuser.user</name><value>hadoop</value></property>
但是,不推荐这样做,HDFS WEBUI,只读权限挺好的,简单浏览即可。如果给与高权限,会有很大的安全问题,造成数据泄露或丢失
5.4 HDFS权限
HDFS中也是有权限控制的,其控制逻辑和Linux文件系统的完全一致(ps:如不理解上图红框内容的含义,建议查看补充关于Linux权限管控的内容)
但是不同的是,大家的Superuser不同 (超级用户不同)
- Linux的超级用户是root
- HDFS文件系统的超级用户: 是启动namenode的用户 (也就是博客里的hadoop用户)
修改权限
在HDFS中,可以使用和Linux一样的授权语句,即:chown和chmod
修改所属用户和组:
hadoop fs -chown[-R] root:root /xxx.txt
hdfs dfs -chown [-R] root:root /xxx.txt
修改权限(-R代表包含子目录)
hadoop fs -chmod[-R]777 /xxx.txt
hdfs dfs -chmod[-R]777 /xxx.txt
如给root用户一个超级权限
hadoop fs -chown root:supergroup /test.txt
给data目录一个777权限
hadoop fs -chmod -R 777 /data
5.5 HDFS客户端 - Jetbrians产品插件
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中
配置hadoop环境变量
配置完hadoop环境变量后需要重启IDEA,不然不生效
配置Big Data Tools插件
打开插件
或者如图指定Windows上解压的Hadoop安装文件夹的etc/hadoop目录也可以,会自动读取配置文件连接上HDFS
现在就可以以图形化的形式使用啦。
5.6 HDFS客户端 - NFS
HDFS提供了基于NFS(Network File System)的插件,可以对外提供NFS网关,供其它系统挂载使用。
NFS 网关支持 NFSv3,并允许将 HDFS 作为客户机本地文件系统的一部分挂载,现在支持:
上传、下载、删除、追加内容
如下图,将HDFS挂载为Windows文件管理器的网络位置(此功能需要专业版,如果是家庭版Windows需要升级为专业版)
配置NFS
配置HDFS需要配置如下内容:
- core-site.xml,新增配置项 以及 hdfs-site.xml,新增配置项
- 开启portmap、nfs3两个新进程
在node1进行如下操作
- 在core-site.xml 内新增如下两项
<property><name>hadoop.proxyuser.hadoop.groups</name><value>*</value>
</property><property><name>hadoop.proxyuser.hadoop.hosts</name><value>*</value>
</property>
2. 在hdfs-site.xml中新增如下项
<property><name>nfs.superuser</name><value>hadoop</value>
</property>
<property><name>nfs.dump.dir</name><value>/tmp/.hdfs-nfs</value>
</property>
<property><name>nfs.exports.allowed.hosts</name><value>192.168.88.1 rw</value>
</property>
nfs.suerpser:NFS操作HDFS系统,所使用的超级用户(hdfs的启动用户为超级用户)
nfs.dump.dir:NFS接收数据上传时使用的临时目录
nfs.exports.allowed.hosts:NFS允许连接的客户端IP和权限,rw表示读写,IP整体或部分可以以*代替
课程设置的允许192.168.88.1以rw连接(这个IP是电脑虚拟网卡VMnet8的IP,连接虚拟机就走这个网卡)
启动NFS功能
- 将配置好的core-site.xml和hdfs-site.xml分发到node2和node3
- 重启Hadoop HDFS集群(先stop-dfs.sh,后start-dfs.sh)
- 停止系统的NFS相关进程
a. systemctl stop nfs; systemctl disable nfs 关闭系统nfs并关闭其开机自启
b. yum remove -y rpcbind 卸载系统自带rpcbind - 启动portmap(HDFS自带的rpcbind功能)(必须以root执行):hdfs --daemon start portmap
- 启动nfs(HDFS自带的nfs功能)(必须以hadoop用户执行):hdfs --daemon start nfs3
检查NFS是否正常
以下操作在node2或node3执行(因为node1卸载了rpcbind,缺少了必要的2个命令)
执行:rpcinfo -p node1
,正常输出如下(有mountd和nfs出现)
执行:showmount -e node1, 可以看到 / 192.168.88.1
在Windows挂载HDFS文件系统
-
开启Windows的NFS功能(此功能需要专业版,如果是家庭版Windows需要升级为专业版)
-
在Windows命令提示符(CMD)内输入:net use X: \192.168.88.101!
-
完成后即可在文件管理器中看到盘符为X的网络位置
-
点击右键客户断开连接
至此,就将HDFS挂载到Windows文件管理器内了,可以进行上传、下载、改名、删除、追加文本等操作。
六 HDFS存储
6.1 存储原理
一个文件要存到服务器,一般情况是把这个文件直接放一个服务器里
HDFS分布式文件存储:把一个文件分成三份(也可能是分成更多分,这里三台服务器,所以是三份),分别存到不同服务器里,取文件的时候,把这三份合并起来反给客户端即可
分布式存储:每个服务器(节点)存储文件的一部分。
多个文件存储时,如下
存在的问题:文件大小不一,不利于统一管理
文件大小不一,不利于统一管理。
解决:设定统一的管理单位,block块
block块
一个文件分成多个Block块,Block块分三份存入对应服务器
问题:如果丢失或损坏了某个Block块呢?
丢失一个Block块就导致文件不完整了,Block块越多,损坏的几率越大
如何解决?通过多个副本(备份)解决,每个Block块都有2个(可修改)备份(副本)
每个副本都复制到其它服务器一份
最后每个块都有2个备份在其它服务器上,安全性极大提高。即数据存入HDFS是分布式存储,即每一个服务器节点,负责数据的一部分。
6.2 fsck命令
在前面我们了解了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的详情
可以看到通过fsck命令我们验证了:
- 文件有多个副本
- 文件被分成多个块存储在hdfs
对于块(block),hdfs默认设置为256MB一个,也就是1GB文件会被划分为4个block存储。
块大小可以通过参数:
<property><name>dfs.blocksize</name><value>268435456</value><description>设置HDFS块大小,单位是b</description></property>
如上,设置为256MB
6.3 NameNode元数据
edits文件
在hdfs中,文件是被划分了一堆堆的block块,那如果文件很大、以及文件很多,Hadoop是如何记录和整理文件和block块的关系呢?答案就在于NameNode
NameNode基于一批edits和一个fsimage文件的配合,完成整个文件系统的管理和维护
edits文件,是一个流水账文件,记录了hdfs中的每一次操作,以及本次操作影响的文件其对应的block
edits记录每一次HDFS的操作,逐渐变得越来越大
所以,会存在多个edits文件,确保不会有超大edits的存在,保证检索性能。
问题在于,当用户想要查看某文件内容,如:/tmp/data/test.txt,就需要在全部的edits中搜索(还需要按顺序从头到尾,避免后期改名或删除),效率非常低。此时就需要合并edits文件,得到最终的结果。将全部的edits文件,合并为最终结果,即可得到一个FSImage文件
NameNode基于edits和FSImage的配合,完成整个文件系统文件的管理。
- 每次对HDFS的操作,均被edits文件记录
- edits达到大小上限后,开启新的edits记录
- 定期进行edits的合并操作
如当前没有fsimage文件, 将全部edits合并为第一个fsimage。如当前已存在fsimage文件,将全部edits和已存在的fsimage进行合并,形成新的fsimage。重复上边123流程。
对于元数据的合并,是一个定时过程,基于:
- dfs.namenode.checkpoint.period,默认3600(秒)即1小时
- dfs.namenode.checkpoint.txns,默认1000000,即100W次事务
只要有一个达到条件就执行。检查是否达到条件,默认60秒检查一次,基于:
- dfs.namenode.checkpoint.check.period,默认60(秒),来决定
SecondaryNameNode的作用
对于元数据的合并,还记得HDFS集群有一个辅助角色:SecondaryNameNode吗?
没错,合并元数据的事情就是它干的,SecondaryNameNode会通过http从NameNode拉取数据(edits和fsimage),然后合并完成后提供给NameNode使用。
6.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份,会尽量找离客户端最近的那一份让其读取
不论读、还是写,NameNode都不经手数据,均是客户端和DataNode直接通讯,不然对NameNode压力太大。HDFS内置网络距离计算算法,可以通过IP地址、路由表来推断网络距离。