五、Hadoop-HDFS
5.1 Hadoop的历史
5.1.1Hadoop的进化史
-
Nutch
- Hadoop最早起源于Nutch。
- Nutch的设计目标是构建一个大型的全网搜索引擎,包括网页抓取、索引、查询等功能
- 但随着抓取网页数量的增加,遇到了严重的可扩展性问题——如何解决数十亿网页的存储和索
引问题。
-
Google
- 2003年、2004年谷歌发表的两篇论文为该问题提供了可行的解决方案。
- GFS : Google File System
- MapReduce :数据计算的方法
-
Doug cutting 花费了自己的两年业余时间,将论文实现了出来
- 2008年1月,HADOOP成为Apache顶级项目
-
Hadoop
- 狭义上来说,hadoop就是单独指代hadoop这个软件,
- 广义上来说,hadoop指代大数据的一个生态圈,包括很多其他的软件(Hadoop生态圈)
5.1.2 Hadoop官网
-
网址:
http://hadoop.apache.org/
https://archive.apache.org/dist/hadoop/common/hadoop-3.1.2/
5.1.3 Hadoop Model
- Hadoop Common 基础型功能
- Hadoop Distributed File System 负责存放数据
- Hadoop YARN 负责资源的调配
- Hadoop MapReduce 大数据的计算框架
- Hadoop Ozone 数据存放到仓库
- Hadoop Submarine 机器学习引擎
5.2 分布式文件系统架构
-
FS File System
- 文件系统是基于硬盘之上的一个文件管理工具
- 我们用户通过操作文件系统可以和硬盘进行解耦
-
DFS ( Distributed File System)
- 分布式文件系统
- 是一种允许文件通过网络在多台主机上分享的文件系统,可让多机器上的多用户分享文件和存储空间。
- 分布式文件管理系统很多,hdfs只是其中一种,不合适小文件。
- HDFS是MapReduce计算的基础
-
DFS出现的原因
- 数据量越来越多,在一个操作系统管辖的范围存不下了,那么就分配到更多的操作系统管理的磁盘中,但是不方便管理和维护,因此迫切需要一种系统来管理多台机器上的文件,这就是分布式文件管理系统 。
- 为了降低文件丢失造成的错误,它会为每个小文件复制多个副本(默认为三个),以此来实现多机器上的多用户分享文件和存储空间。
5.2.1 文件切分思想
-
文件存的原因
- 文件存放在一个磁盘上的效率肯定是低的
- 读取效率低
- 如果文件特别大会超过单机的存储范围
- 文件存放在一个磁盘上的效率肯定是低的
-
解决办法
-
切分数据
-
对字节数组进行切分
-
字节数组
- 文件在磁盘真实存储文件的抽象概念
- 数组可以拆分和组装,源文件不会收到影响
-
-
拼接数据
- 按照数组的偏移量将数据连接到一起,将字节数组链接到一起
- 偏移量
- 当前数据在数组中的相对位置,可以理解为下标
- 数组都有对应的索引(下标),可以快速的定位数据
-
数据存储的原理
- 不管文件的大小,所有的文件都是由字节数组构成的
- 如果我们要切分文件,就是将一个字节数组分成多份
- 我们将切分后的数据拼接到一起,数据仍然可以继续使用
- 我们需要根据数据的偏移量将他们重新的拼接到一起
-
5.2.2 Block拆分标准
- 拆分的数据块(Block)需要等大
- 可以简化数据计算的时候的问题的复杂度
- 进行分布式算法设计的时候,数据不统一,算法很难设计
- 数据拉取的时候时间相对一致
- 通过偏移量就可以指导这个块的位置
- 相同文件,分成的数据块大小应该相等
- 可以简化数据计算的时候的问题的复杂度
- 数据块(Block)
- 数据被切分后的一个整体称之为块
- 在H1默认大小为64M,在H2及其后默认大小为128M
- 同一个文件中,每个数据块大小要一致,除了最后一个节点外
- 不同文件中,块的大小可以不一致
- 文件大小不同可以设置不同的块的数量
- 真实情况下,会根据文件大小和集群节点的数量综合考虑块的大小
- 数据块的个数 =Ceil(文件大小/每个块的大小)
- 注意事项
- HDFS中一旦文件被存储,数据不允许被修改
- 修改会影响偏移量
- 修改会导致数据倾斜
- 修改数据会导致蝴蝶效益
- 但是可以被追加,但是不推荐
- 追加设置需要手动打开
- 一般HDFS存储的都是历史数据。所以 将来Hadoop的mr都用来进行离线数据的处理
- 块的大小一旦文件上传之后就不允许被修改
- 128m -512M
- 如果数据文件的切割点128M整好是一个单词的中间部分,切分数据如何保证数据的完整性?
- HDFS中一旦文件被存储,数据不允许被修改
5.2.3 Block数据安全
- 对存储的数据进行备份
- 备份的数据肯定不能存放在一个节点上
- 使用数据的时候可以就近获取数据
- 备份的数量要小于等于节点的数量
- 每个数据块会有3个副本(3个相同的文件),相同副本是不会存放在同一个节点上的
- 副本的数量可以变更
- 可能近期的数据被分析的可能性跟大,副本数可以多设置几个
- 后期数据很少被分析,可以减少副本数
5.2.4 Block管理效率
-
需要专门给节点进行分工
- 存储 DataNode
- 记录 NameNode
- 日志 secondaryNameNode
5.2.5 HDFS的特点
- 优点
- 高容错率
- 保存多个副本,且提供容错机制。
- 副本丢失或宕机自动恢复。默认存3份。
- 运行在廉价的机器上
- 通过副本提高可靠性
- 提供了容错和恢复机制
- 适合批处理
- 移动计算而非数据
- 数据位置暴露给计算框架。NameNode上有位置
- 适合大数据的处理
- TB,甚至PB级数据
- 百万规模以上的文件数量
- 10K+节点规模
- 流式数据访问
- 一次写入,多次读取,高吞吐量,所以可以同时处理大量数据
- 高容错率
- 缺点
- 不擅长低延时数据访问
- 比如毫秒级
- 不擅长小文件的分区
- 占用NameNode大量内存
- 磁盘寻道时间超过读取时间
- 不擅长并发写入,文件随机修改
- 一个文件只能有一个写入者
- 仅支持append,也就是添加(有组件实现删等)
- 不擅长低延时数据访问
5.3 Hadoop完全分布式搭建
主机\Hadoop节点 | NameNode | SecondaryNameNode | DataNode |
---|---|---|---|
node01 | √ | √ | |
node02 | √ | √ | |
node03 | √ |
5.3.1 准备安装环境
[root@node01 ~]# tar -zxvf hadoop-3.1.2.tar.gz
[root@node01 ~]# mkdir -p /opt/yjx/
[root@node01 ~]# mv hadoop-3.1.2 /opt/yjx/
[root@node01 ~]# cd /opt/yjx/hadoop-3.1.2/etc/hadoop/
5.3.2 修改集群环境
-
[root@node01 hadoop]# vim hadoop-env.sh
#直接在文件的最后添加 export JAVA_HOME=/usr/java/jdk1.8.0_231-amd64 export HDFS_NAMENODE_USER=root export HDFS_DATANODE_USER=root export HDFS_SECONDARYNAMENODE_USER=root
5.3.3 修改配置文件
-
[root@node01 hadoop]# vim core-site.xml
<configuration> <property> <name>fs.defaultFS</name> <value>hdfs://node01:9000</value> </property> <property> <name>hadoop.tmp.dir</name> <value>/var/yjx/hadoop/full</value> </property> </configuration>
-
[root@node01 hadoop]# vim hdfs-site.xml
<configuration> <property> <name>dfs.namenode.secondary.http-address</name> <value>node02:50090</value> </property> <property> <name>dfs.namenode.secondary.https-address</name> <value>node02:50091</value> </property> <property> <name>dfs.replication</name> <value>2</value> </property> </configuration>
-
[root@node01 hadoop]# vim workers
node01 node02 node03
5.3.4 拷贝分发软件
-
将配置好的软件分发到其他主机
[root@node02 ~]# scp -r root@node01:/opt/yjx/hadoop-3.1.2 /opt/yjx/ [root@node03 ~]# scp -r root@node01:/opt/yjx/hadoop-3.1.2 /opt/yjx/
5.3.5 修改环境变量
-
[root@node01 hadoop]# vim /etc/profile
export HADOOP_HOME=/opt/yjx/hadoop-3.1.2 export PATH=$HADOOP_HOME/bin:$HADOOP_HOME/sbin:$PATH
-
将环境变量拷贝到其他主机
[root@node01 yjx]# scp /etc/profile root@node02:/etc/profile [root@node01 yjx]# scp /etc/profile root@node03:/etc/profile
-
重新加载三台服务器的环境变量
【123】# source /etc/profile
5.3.6 格式化NameNode
- [root@node01 yjx]# hdfs namenode -format
- [root@node01 yjx]# start-dfs.sh
5.3.7 测试集群
-
输入网址:http://192.168.101.88:9870
-
本地新建文件夹测试
hdfs dfs -mkdir -p /yjx
图片结果显示:
-
本地上传文件测试
hdfs dfs -put zookeeper-3.4.5.tar.gz /yjx/
5.3.8 关闭集群
-
关闭集群
[root@node01 ~]# stop-dfs.sh
-
关机然后拍摄快照
[123]# shutdown -h now
5.4 Hadoop集群命令
5.4.1 命令分类
-
Hadoop fs
该命令可以用于其他文件系统,不止是hdfs文件系统内,也就是说该命令的使用范围更广
-
Hadoop dfs
专门针对hdfs分布式文件系统
-
hdfs dfs(推荐)
- 和上面的命令作用相同,相比于上面的命令更为推荐,并且当使用hadoop dfs时内部会被转为hdfs dfs命令
5.4.2 Hadoop FS命令
-
介绍
- 调用文件系统(FS)Shell命令应使用 bin/hadoop fs 的形式。 所有的的FS shell命令使用URI路径作为参数。
-
官方命令文档
- http://hadoop.apache.org/docs/r1.0.4/cn/hdfs_shell.html
-
常见命令
1 hadoop fs -ls <path> 列出指定目录下的内容,支持pattern匹配。输出格式如filename(full path)<r n>size.n代表备份数。 2 hadoop fs -lsr <path> 递归列出该路径下所有子目录信息 3 hadoop fs -du<path>显示目录中所有文件大小,或者指定一个文件时,显示此文件大小 4 hadoop fs -dus<path>显示文件大小 相当于 linux的du -sb s代表显示只显示总计,列出最后的和 b代表显示文件大 小时以byte为单位 5 hadoop fs -mv <src> <dst> 将目标文件移动到指定路径下,当src为多个文件,dst必须为目录 6 hadoop fs -cp <src> <dst>拷贝文件到目标位置,src为多个文件时,dst必须是个目录 7 hadoop fs -rm [skipTrash] <src>删除匹配pattern的指定文件 8 hadoop fs -rmr[skipTrash] <src>递归删除文件目录及文件 9 hadoop fs -rmi [skipTrash] <src>为了避免误删数据,加了一个确认 10 hadoop fs -put <> ... <dst>从本地系统拷贝到dfs中 11 hadoop fs -copyFromLocal<localsrc>...<dst>从本地系统拷贝到dfs中,与-put一样 12 hadoop fs -moveFromLocal <localsrc>...<dst>从本地系统拷贝文件到dfs中,拷贝完删除源文件 13 hadoop fs-get [-ignoreCrc] [-crc] <src> <localdst> 从dfs中拷贝文件到本地系统,文件匹配 pattern,若是多个文件,dst必须是个目录14 hadoop fs -getmerge <src> <localdst>从dfs中 拷贝多个文件合并排序为一个文件到本地文件系统15 hadoop fs -cat <src>输出文件内容16 hadoop fs -copyTolocal [-ignoreCre] [-crc] <src> <localdst>与 -get一致17 hadoop fs -mkdir <path>在指定位置创建目录18 hadoop fs -setrep [-R] [-w] <rep> <path/file>设置文件的备份 级别,-R标志控制是否递归设置子目录及文件19 hadoop fs -chmod [-R] <MODE[,MODE]...|OCTALMODE>PATH修改文件权限, -R递归修改 mode为a+r,g-w,+rwx ,octalmode 为75520 hadoop fs -chown [-R] [OWNER][:[GROUP]] PATH递归修改文件所有者和组21 hadoop fs -count[q] <path>统计文件个数及占空间情况,输出表格列的含义分别为: DIR_COUNT.FILE_COUNT.CONTENT_SIZE.FILE_NAME,如果加-q 的话,还会列出 QUOTA,REMAINING_QUOTA,REMAINING_SPACE_QUOTA
5.4.3 hdfs dfs 命令
-mkdir 创建目录 hdfs dfs -mkdir [-p] < paths>
-ls 查看目录下内容,包括文件名,权限,所有者,大小和修改时间 hdfs dfs -ls [-R] <
args>
-put 将本地文件或目录上传到HDFS中的路径 hdfs dfs -put < localsrc> … < dst>
-get 将文件或目录从HDFS中的路径拷贝到本地文件路径 hdfs dfs -get [-ignoreCrc] [-crc]
< src> < localdst>
选项:-ignorecrc选项复制CRC校验失败的文件。-crc选项复制文件和CRC。
-du 显示给定目录中包含的文件和目录的大小或文件的长度,用字节大小表示。 hdfs dfs -du [-
s] [-h] URI [URI …] 选项:-s选项将显示文件长度的汇总摘要,而不是单个文件。-h选项将以“人可
读”的方式格式化文件大小(例如64.0m而不是67108864);第一列标示该目录下总文件大小,第二列标示该
目录下所有文件在集群上的总存储大小和你的副本数相关(第二列内容=文件大小*副本数),第三列标示你查
询的目录
-dus 显示文件长度的摘要。 hdfs dfs -dus < args> 注意:不推荐使用此命令。而是使用
hdfs dfs -du -s。
-mv 在HDFS文件系统中,将文件或目录从HDFS的源路径移动到目标路径。不允许跨文件系统移动文件。
-cp 在HDFS文件系统中,将文件或目录复制到目标路径下 hdfs dfs -cp [-f] [-p | -p
[topax] ] URI [ URI …] < dest> 选项:-f选项覆盖已经存在的目标。-p选项将保留文件属性
[topx](时间戳,所有权,权限,ACL,XAttr)。如果指定了-p且没有arg,则保留时间戳,所有权和权
限。如果指定了-pa,则还保留权限,因为ACL是一组超级权限。确定是否保留原始命名空间扩展属性与-p标
志无关。
-copyFromLocal 从本地复制文件到hdfs文件系统(与-put命令相似)hdfs dfs -copyFromLocal <
localsrc> URI 选项:如果目标已存在,则-f选项将覆盖目标。
-copyToLocal 复制hdfs文件系统中的文件到本地 (与-get命令相似) hdfs dfs -
copyToLocal [-ignorecrc] [-crc] URI < localdst>
-rm 删除一个文件或目录 hdfs dfs -rm [-f] [-r|-R] [-skipTrash] URI [URI …] 选
项:如果文件不存在,-f选项将不显示诊断消息或修改退出状态以反映错误。-R选项以递归方式删除目录及其
下的任何内容。-r选项等效于-R。-skipTrash选项将绕过垃圾桶(如果已启用),并立即删除指定的文件。
当需要从超配额目录中删除文件时,这非常有用。
-cat 显示文件内容到标准输出上。 hdfs dfs -cat URI [URI …]
-text 获取源文件并以文本格式输出文件。允许的格式为zip和TextRecordInputStream。 hdfs
dfs -text
-touchz 创建一个零长度的文件。 hdfs dfs -touchz URI [URI …]
-stat 显示文件所占块数(%b),文件名(%n),块大小(%n),复制数(%r),修改时间(%y%Y) hdfs
dfs -stat URI [URI …]
-tail 显示文件的最后1kb内容到标准输出 hdfs dfs -tail [-f] URI 选项: -f选项将
在文件增长时输出附加数据,如在Unix中一样。
-count 统计与指定文件模式匹配的路径下的目录,文件和字节数 hdfs dfs -count [-q] [-h]
< paths>
-getmerge 将源目录和目标文件作为输入,并将src中的文件连接到目标本地文件(把两个文件的内容合
并起来) hdfs dfs -getmerge < src> < localdst> [addnl] 注:合并后的文件位于当前目
录,不在hdfs中,是本地文件
-grep 从hdfs上过滤包含某个字符的行内容 hdfs dfs -cat < srcpath> | grep 过滤字段
-chown hdfs上文件权限修改 hadoop fs -chown [-R] [OWNER][:[GROUP]] URI [URI ]#修
改文件的所有者 例如:hdfs dfs -chown -R Administrator:Administrator /user/
-distcp 最常用在集群之间的拷贝:hadoop distcp hdfs://master1:8020/foo/bar
hdfs://master2:8020/bar/foo
5.5 文件的数据类型
5.5.1文件类型的分类
-
元数据
- 描述文件信息的数据
File 文件名 Size 文件大小(字节) Blocks 文件使用的数据块总数 IO Block 数据块的大小 regular file:文件类型(常规文件) Device 设备编号 Inode 文件所在的Inode Links 硬链接次数 Access 权限 Uid 属主id/用户 Gid 属组id/组名 Access Time:简写为atime,表示文件的访问时间。当文件内容被访问时,更新这个时间 Modify Time:简写为mtime,表示文件内容的修改时间,当文件的数据内容被修改时,更新这个 时间。 Change Time:简写为ctime,表示文件的状态时间,当文件的状态被修改时,更新这个时间,例 如文件的链接数,大小,权限,Blocks数。
-
文件数据
- 真实存在于文件中的数据,这个数据就是存储在硬盘上的二级制
5.6 NameNode(NN)
5.6.1 功能
1.接受客户端的请求(读写服务)
-
当客户端访问HDFS的时候,都会通过NN获取或者是生成BLK对应的DN信息,但是真实存储或者读取数据的时候,都是客户端直接去DN建立连接
-
NameNode存放文件与Block的映射关系
-
NameNode会记录Block与DataNode的映射关系,但是不会持久化存储
2.保存文件的元数据信息
- 包括以下信息
- 文件的归属
- 文件的权限
- 文件的大小与时间
- Block信息,但是Block的位置信息不会持久化,需要每次开启集群的时候通过DN上报
3. 收集Block信息
- 系统启动时
- NN关机的时候是不会存储任意的Block与DN的映射信息
- DN启动的时候,会将自己节点上存储的Block信息回报给NN
- NN接受请求之后重新生成新的映射关系
- Block–DN3
- 如果某个数据块的副本数小于设置数,那么NN会将这个副本拷贝到其他节点
- 集群运行中(心跳机制)
- NN与DN保持心跳机制,每3秒钟发送一次验证是否连接,如果超过3秒钟没有心跳,本次心跳失败(暂时标记为不可用)
- 如果DN超过10分钟+30秒没有心跳,那么NN就会将当前的DN存储的数据转存到其他的节点
5.6.2 性能
- NameNode为了效率,将所有的操作都在内存中完成
- NameNode不会和磁盘进行任何的数据交换
- 问题:
- 数据不能持久化
- 数据保存在内存中,掉电易失
- 问题:
5.7 DataNode(DN)
5.7.1 功能
-
存放数据文件
- 存放文件的数据信息和校验文件完整性的校验信息
- 数据会存放在硬盘上
- DN上面存放的都是BLK
- NameNode不适合存储小文件,因为小文件会形成大量的元数据和映射信息,有可能这些信息会大于文件的大小
-
汇报
- 启动时
- 汇报之前先验证Block文件是否被损坏
- 如果Block没有问题,将向NN汇报当前DN上的Block信息
- 运行中
- 向NN保持心跳机制,汇报当前节点的数据存储信息
- 客户可以向DN读写数据
- 启动时
-
注意:
-
当客户端读写数据的时候,首先去NN查询文件的Block与DN的映射
-
然后客户端直接与DN建立连接,然后读写数据
-
5.8 SecondaryNameNode
对于NameNode出现问题的时候可以进行恢复NameNode信息的解决方案
5.8.1传统解决方案
-
日志记录
- 做任何操作之前都先记录日志,当NN下次启动的时候,只需要重新按照以前的日志“重做”一遍即可
- 缺点:
- edits文件大小不可控,随着时间的发展,集群启动的时间会越来越长
- 有可能日志中存在大量的无效的日志
- 优点:
- 绝对不会丢失数据
-
拍摄快照
- 我们可以将内存中的数据写到硬盘上
- 序列化
- 启动集群时还可以将硬盘上的数据写回内存中
- 反序列化
- 缺点:
- 关机时间过长
- 如果异常关机,数据还在内存中,就没法写入到硬盘中
- 如果写出频率过高,导致内存使用率低
- 优点
- 启动时间较短
- 我们可以将内存中的数据写到硬盘上
-
NameNode将元数据存储到磁盘上的图解
- 两个不同文件解释
- fsimage(FileSystem 镜像) - 它是在 NameNode 启动时对整个文件系统的快照
- edit logs - 它是在 NameNode 启动后,对文件系统的改动序列
-
NameNode的存储方式存在的问题
- 以上两种方式的一些缺点
- 日志
- NameNode运行了很长时间后产生的edit logs会很大
- 有可能日志中存在大量的无效的日志
- 快照
- 关机时间过长
- 如果异常关机,数据还在内存中,就丢失了很多的改动操作,这个时候的fsimage版本就非常旧,也没法写入到硬盘中
- 如果写出频率过高,导致内存使用率低
- 日志
由于这些传统的解决方案出现的问题,于是出现了SNN的解决方案
- 以上两种方式的一些缺点
5.8.2 SNN解决方案
-
解决思路
- 日志(edits)+快照(fsimage)
- 让日志大小可控
- 定时快照保存
- fsimage:当前内存中文件系统的快照(序列化)
- 合并NameNode的edit logs到fsimage文件中
- 日志(edits)+快照(fsimage)
-
什么是SNN节点
SecondaryNameNode节点的主要功能是周期性将元数据节点的镜像文件和修改日志进行合并,以防日志文件过大
5.8.3 SNN的数据恢复
-
没有格式化id之前的数据信息
-
强行杀死NameNode节点
- cd /var/yjx/hadoop/full/dfs/name/current
- 输入 jps命令
- kill -9 7208
-
清空namenode下name中的fsimage和edtis文件
[root@node01 ~]# rm -rf /var/yjx/hadoop/full/dfs/name/current/*
-
node02中的secondarynamenode下的name中的fsimage和edits复制到namenode对应文件夹中
[root@node01 current]# scp -r root@node02:/var/yjx/hadoop/full/dfs/namesecondary/current/* /var/yjx/hadoop/full/dfs/name/current/
-
启动NameNode
start-dfs.sh
-
访问namenode节点页面,成功
-
但同时有部分数据丢失
丢失的数据为一个文件等分大小后的最后一部分的不完整的Block块