HDFS概述和超详细的读写流程介绍
HDFS是Hadoop提供的一套用于进行分布式存储的文件系统
概述
- HDFS的基本结构是典型的主从结构 – NameNode(主节点)和DataNode(从节点) ;
- Namenode负责管理整个文件系统的元数据;
- Datanode复制储存文件数据块;
- SecondaryNameNode有两个作用,一是镜像备份(fsimage),二是日志(edits)与镜像(fsimage)的定期合并。它既不能取代NameNode也不是NameNode的备份。
- 文件会按照固定的大小(blocksize)切成若干块(block)后,分布式存储在若干台datanode上。
- HDFS会自动的对数据进行备份,这个备份称之为副本,每一个文件块(block)会有多个副本,并存放在不同的Datanode上
- Datanode会定期向Namenode汇报自身所保存的文件block信息,称为心跳机制
概念解释:
-
元数据:元数据的信息主要包括
-
文件的存储位置
-
文件的权限
-
文件的大小
-
Block的大小
-
BlockID
-
副本数量
-
BlockID和DataNode的映射关系,
注意:默认情况下,一个BlockID对应三个DataNode的地址(默认的备份数量为三)
-
-
block:
- block是Hdfs中的数据存储的基本单位
- block的大小默认是128MB,可通过配置文件hdfs-site.xml 中,设定dfs.blockSize的值来设置block的大小
- block只存储一个文件的内容,不足128M那么这个文件是多大对应的Block就是多大。
例如:一个文件是10MB则 其对应的Block就是10MB
不存在多个文件内容装在一个block拼接凑128M的情况 - Hdfs会给block进行编号-blockID
-
Packet:
packet是第二大的单位,它是client端向DataNode,或DataNode的PipLine之间传数据的基本单位,默认64KB
-
Chunk:
chunk是最小的单位,它是client向DataNode,或DataNode的PipLine之间进行数据校验的基本单位,默认512Byte,因为用作校验,故每个chunk需要带有4Byte的校验位。所以实际每个chunk写入packet的大小为516Byte。由此可见真实数据与校验值数据的比值约为128 : 1。
-
心跳机制:
主节点和从节点之间的通信是通过心跳机制(心跳实际上是一个RPC函数)实现的;所谓“心跳”是一种形象化描述,指的是持续的按照一定频率在运行,类似于心脏在永无休止的跳动。
-
网络拓扑结构:
网络中通信线路和设备的分布情况和连接状态所形成的物理布局
-
RPC:远程过程调用协议
RPC是指远程过程调用,一个进程使用这种协议向网络中的另一台计算机上的程序请求服务,不需要了解底层网络技术的协议
hadoop的整个体系结构就是构建在RPC之上的
-
socket string:
socket Address 基于TCP协议
HDFS读取文件过程
大致流程:
Client向namenode 发送要读取的文件路径,namenode 将返回该文件的元信息(主要包含block的位置信息),Client根据元信息从相应的datanode上获取block的数据在本地进行追加合并,获得完整的文件
详细说明:
-
每个block有多个副本,通过rpc获得文件的第一个block的locations,同一block按照副本数会返回多个locations,这些locations依据两个规则进行排序
- 按照网络拓扑结构排序,距离Client近的排在前面。
- 心跳机制中超时汇报的datanode状态为STALE,排在后面
Client根据就近原则选择datanode,建立socket Stream(FSDataInputStream),重复调用DataInputeStream的read方法,读取block。
-
读取完一个block块之后都会进行checksum验证,如果出错,或者在读数据的时候,Client和datanode的通讯发生异常,就会尝试从 与在读的block最近的另一个datenode中读取数据,并且会将发生错误的datanode,汇报给namenode。剩余的blocks读的时候就会直接跳过该datanode。
-
datanode以packet为单位发送数据,客户端以packet为单位进行接受,先缓存,后写入磁盘
HDFS写入文件过程
大致流程:
首先Client与namenode进行通讯,由namenode确认是否可以写文件,如果可以,则返回接收文件block的datanode,再由Client按顺序将文件的block传递给相应的datanode,接收到block的datanode负责向其他datanode传送block的副本
详细说明:
- namenode主要通过写入的目标文件是否已经存在,以及Client是否有权限来判断是否可以写入,符合要求之后,依据机架感知、网络拓扑、副本机制返回datanode的连接列表。
- Client依次请求每一个block块应该上传到哪一个datanode,namenode会根据设定的副本数量,返回相同数量的datanode节点
- client根据NameNode返回的可写的DataNode列表(A,B,C),向最近的一个DataNode节点A请求上传数据(本质上是RPC调用,建立pipeline),A接收到请求后,会根据Client发送的Datanode节点列表,继续调用B,B再调用C,建成的pipeline管道。
- client会把block数据切成packet排成data queue,等待上传
- client每向第一个DataNode写入一个packet,这个packet便会直接在pipeline里传给第二个、第三个…DataNode。
- client会维护一个ack queue,也是由packet组成,每个DataNode写完一个块后,会返回确认信息。当pipeline中的所有datanode都表示已经收到的时候,这时akc queue才会把对应的packet包移除掉。
- 如果在写的过程中某个datanode发生错误,会采取以下几步:
- pipeline被关闭掉;
- 为了防止丢包 ack queue里的packet会同步到data queue里;
- 把产生错误的datanode上当前在写但未完成的block删掉;
- block剩下的部分被写到剩下的两个正常的datanode中;
- namenode找到另外的datanode去创建这个块的复制。
- client把所有的数据都刷到pipeline里然后等待ack信息,收到最后一个ack后,通知datanode把文件标示为已完成。
block\packet\chunk的关系:
在client端向DataNode传数据的时候,HDFSOutputStream会有一个chunk buff,写满一个chunk后,会计算校验和并写入当前的chunk。之后再把带有校验和的chunk写入packet,当一个packet写满后,packet会进入dataQueue队列,其他的DataNode就是从这个dataQueue获取client端上传的数据并存储的。同时一个DataNode成功存储一个packet后之后会返回一个ack packet,放入ack Queue中。