一、HDFS简介
分布式文件存储
随着数据量的不断增大,文件的大小取决于单机存储的上限,这显然满足不了我们的需求。HDFS将大文件切块,部署到不同的机器节点上,完成分布式存储。
![](https://github.com/AlgoricLi/MyImage/blob/master/BigData/HDFS/HDFS%E6%9C%BA%E6%9E%B6.png?raw=true)
在分布式系统中,计算机节点放在机架上,每个机架存在很多节点,不同机架之间通过交换机通信,同一机架不同节点之间通过网络互连。
远程调用:远程过程调用(RPC)是一种常用的分布式网络通信协议,它允许运行于
一台计算机的程序调用另一台计算机的子程序,同时将网络的通信细节隐藏起来, 使得用户无须额外地为这个交互作用编程。分布式系统之间的通信大都通过RPC实现。
二、HDFS结构
![](https://github.com/AlgoricLi/MyImage/blob/master/BigData/HDFS/HDFS%E7%B3%BB%E7%BB%9F%E6%9E%B6%E6%9E%84.png?raw=true)
- 名称节点(NameNode) 主节点(Master)
- 数据节点 (DataNode) 从节点(Slave)
名称节点负责文件和目录的创建、删除和重命名等,同时管理数据节点与文件块的映射关系;数据节点负责数据的存储和读取。
客户端读数据会先访问名称节点,获取数据块对应数据节点的位置,进而读取数据,写入数据也会由名称节点分配存储位置,再向对应数据节点写入数据。
1. 名称节点
名称节点的两个核心数据结构:
-
FsImage
FsImage用于维护文件系统树以及文件树中所有的文件和文件夹的元数据
元数据信息包括文件的复制等级、修改和访问时间、访问权限、块大小以及组成文件的块
注:FsImage文件没有记录块存储在哪个节点,数据块和节点映射信息保存在NameNode的内存中。 -
EditLog
记录对所有文件创建、删除、重命名等操作。
SecondaryNameNode
![](https://github.com/AlgoricLi/MyImage/blob/master/BigData/HDFS/HDFS__SecondaryNameNode.png?raw=true)
-
secondDaryNameNode会定期与NameNode通信,暂停EditLog,创建新的EditNew,瞬间完成 。
-
FsImage和EditLog会不断增大,secondDaryNameNode可以解决这个问题,它会定期拉取这两个文件,进行一个合并过程,通过执行EditLog文件,得到最新的FsImage,推送到NameNode, 代替原有的FsImage,同时使用editNew代替原有EditLog文件。
-
secondDaryNameNode 还可以作为冷备份,在NameNode宕机后使用它进行恢复
2. 数据节点
HdFS按块存储,每个块默认大小是128M,远远大于普通文件系统,这样做的目的是为了最小化寻址开销。
2.1 文件系统存储原理
文件存储在磁盘上,磁盘读取数据靠的是机械运动。
- 当需要从磁盘读取数据时,系统会将数据逻辑地址传给磁盘,磁盘的控制电路按照寻址逻辑将逻辑地址翻译成物理地址,即确定要读的数据在哪个磁道,哪个扇区。为了读取这个扇区的数据,需要将磁头放到这个扇区上方,
- 为了实现这一点,磁头需要移动对准相应磁道,这个过程叫做寻道,所耗费时间叫做寻道时间,然后磁盘旋转将目标扇区旋转到磁头下,这个过程耗费的时间叫做旋转时间。
- 最后是对读取数据的传输。
所以每次读取数据花费的时间可以分为寻道时间、旋转延迟、传输时间三个部分
HDFS读取文件的时间就可以分为寻址时间和数据传输时间,如果文件太小,在名称节点的映射列表会过大,影响寻址时间,寻址时间如果大于传输时间,就没有意义了。所以设置成大文件。
如果Block设置过大,在MapReduce任务中,Map或者Reduce任务的个数小于集群机器数量,会使得作业运行效率很低。
2.2 数据冗余
HDFS采取多副本进行数据冗余,一个数据块默认冗余三个副本,其中一个副本放到不同机架上,其它两个副本放在同一个机架不同节点上。
![](https://github.com/AlgoricLi/MyImage/blob/master/BigData/HDFS/HDFS%E6%95%B0%E6%8D%AE%E5%86%97%E4%BD%99.png?raw=true)
如图,数据块1被分别存放到数据节点A和C上,数据块2被存放在数据节点A和B上
2.3 数据错误
网络传输或者磁盘读写可能会导致数据错误
解决办法:
- 在文件被创建的时候,客户端对文件进行摘录,并写入数据同一路径隐藏文件中。
- 客户端读取数据后会进行数据块的校验,一般使用md5或者sha1算法,如果出错会请求其它节点的数据块,并向名称节点汇报,名称节点会定期检查并重新复制这个block.
三、HDFS读写过程
写入:
- 提交写操作到NameNode,判断是否有权限。NameNode为其分配数据节点,返回信息。
- 进行数据交互,把数据进行分块,先写完第一个副本,拷贝到第二个节点,再到第三个节点,形成“流水线复制”。
- 为了保证节点数据准确,接收到数据的数据节点要向发送者返回ACK确认信息,确认包会顺着流水线逆流而上,经过各个节点到达客户端。
读取:
HDFS提供了一个API可以确定一个数据节点所属的机架ID,客户端也可以调用API获取自己所属的机架ID
-
客户端请求NameNode,计算出距离client最近的副本,返回元数据信息;
当客户端读取数据时,从名称节点获得数据块不同副本的存放位置列表,列表中包含了副本所在的数据节点,可以调用API来确定客户端和这些数据节点所属的机架ID,当发现某个数据块副本对应的机架ID和客户端对应的机架ID相同时,就优先选择该副本读取数据,如果没有发现,就随机选择一个副本读取数据 -
客户端读取对应数据块信息。
本文参考厦门大学林子雨老师的大数据课程