hdfs的定义
hdfs(hadoop distributed file system),它是一个文件系统,用于存储文件,通过目录树来定位文件;其次,它是分布式的,由很多服务器联合起来实现其功能,集群中的服务器有各自的角色。
一、组成架构
- namenode(nn) : 集群的master,它是一个主管,管理者
(1) 管理hdfs的命名空间
(2) 配置副本策略
(3) 管理数据块(block)映射信息
(4) 处理客户端读写请求 - datanode(dn) : 集群的slave。nn下达命令,datanode执行实际操作。
(1) 存储实际的数据块
(2) 执行数据块的读/写操作 - client : 客户端
(1) 文件切分。文件上传hdfs的时候,client将文件切分成一个个的block,然后进行上传
(2) 与namenode交互,获取文件的位置信息
(3) 与datanode交互,读取或写入数据 - secondarynamenode : 并非namenode的热备。当namenode挂掉的时候,它并不能马上替换namenode并提供服务。
(1) 辅助namenode,分担其工作量,比如定期合并fsimage和edits,并推送给namenode
(2) 在紧急情况下可辅助恢复namenode
二、优缺点
- 缺点
- 优点
副本节点的选择
三、读流程
1.客户端向 namenode 发送读取请求,请求包括要读取的文件名和文件块的起始位置。
2.namenode 根据请求的文件名,查询文件所对应的块列表,并返回给客户端块列表以及每个块所在的 datanode 列表。
3.客户端根据返回的块列表和 datanode 列表,选择一个 datanode 开始读取数据。如果选择的 datanode 不可用,则会选择另外一个 datanode。
3.客户端向选择的 datanode 发送读取请求,请求包括要读取的块的起始位置和长度。
4.datanode 接收到读取请求后,从本地磁盘读取数据块,并将数据块返回给客户端。
5.如果 datanode 上的数据块副本不足,则会从其他 datanode 上获取数据块副本。
tip:client从namenode处获取到元数据信息,包括每个数据块的id、副本所在datanode的地址等,紧接着会按照client设置好的实现策略(最近性,负载均衡性等)选择一个或多个datanode来读取数据块。
四、namenode和seconderynamenode
secondarynamenode工作流程
- 第一阶段:namenode启动
(1)第一次启动namenode格式化后,创建fsimage和edits文件。如果不是第一次启动,直接加载编辑日志和镜像文件到内存。
(2)客户端对元数据进行增删改的请求。
(3)namenode记录操作日志,更新滚动日志。
(4)namenode在内存中对元数据进行增删改。 - 第二阶段:secondary namenode工作
(1)secondary namenode询问namenode是否需要checkpoint。直接带回namenode是否检查结果。
(2)secondary namenode请求执行checkpoint。
(3)namenode滚动正在写的edits日志。
(4)将滚动前的编辑日志和镜像文件拷贝到secondary namenode。
(5)secondary namenode加载编辑日志和镜像文件到内存,并合并。
(6)生成新的镜像文件fsimage.chkpoint。
(7)拷贝fsimage.chkpoint到namenode。
(8)namenode将fsimage.chkpoint重新命名成fsimage。
五、写流程
(1)客户端通过distributed filesystem模块向namenode请求上传文件,namenode检查目标文件是否已存在,父目录是否存在,客户端是否有写权限。
(2)namenode返回是否可以上传。
(3)客户端请求第一个 block上传到哪几个datanode服务器上(数据的切分在客户端完成)。
(4)namenode返回3个datanode节点,分别为dn1、dn2、dn3(返回dn数据存储列表)。
(5)客户端通过fsdataoutputstream模块请求dn1上传数据,dn1收到请求会继续调用dn2,然后dn2调用dn3,将这个通信管道建立完成。(pipline管道传输)
(6)dn1、dn2、dn3逐级应答客户端。
(7)客户端开始往dn1上传第一个block(先从磁盘读取数据放到一个本地内存缓存),以packet为单位,dn1收到一个packet就会传给dn2,dn2传给dn3;dn1每传一个packet会放入一个应答队列等待应答(ack校验)。
(8)当一个block传输完成之后,客户端再次请求namenode上传第二个block的服务器。(重复执行3-7步)。
值得注意的是:
在hdfs的写流程中,edit文件记录了所有的namenode操作,包括文件的创建、删除、修改等。当客户端向namenode发送写请求时,namenode会将操作记录到内存中的edit文件中。当内存中的edit文件达到一定大小时,namenode会将其刷写到磁盘上的edit文件中。同时,secondarynamenode/jns会帮助namenode定期将内存中的edit文件刷写到磁盘中合并fsimage,以避免因为系统崩溃等原因导致内存中的数据丢失。
因此,edit文件的更改与hdfs的写流程是相互独立的。edit文件的更改只与namenode的操作有关,而不与datanode的写入操作有关。当namenode接收到客户端的写请求时,会更新内存中的edit文件,而不是在datanode写入数据时更新edit文件。因此,edit文件的更改和数据块的写入是两个独立的过程。
既然都能够写入wal日志文件,为什么不干脆直接写入datanode呢?
此处有个可能会忽略的问题,insert操作是随机写入的,会花费大量的寻址时间,而wal日志文件是顺序写入的,其性能比随机写入快很多,预写日志这种方式在很多组件中都有利用。
发表评论