您的位置 首页 java

Hadoop 系列之 HDFS

花絮

上一篇文章 Hadoop 系列之 1.0和2.0架构 中,提到了 Google 的三驾马车,关于 分布式存储 ,计算以及列式存储的论文,分别对应开源的 HDFS ,Mapreduce以及 HBase。这里的 HDFS 是 分布式 文件系统,主要用于数据的存储。它的应用非常广泛,作为一款开源的文件系统,其高容错性、可靠性以及可部署在廉价机器上的特点,受到很多开发者的青睐。

今天我们就来撩一撩这个分布式文系统,HDFS 全称 Hadoop Distributed File System,初学者只需要知道我们大数据解决的两个主要问题就可以了,一个是数据如何存储,另一个是数据如何计算。本文的 HDFS 就是数据存储的一种方式。好了,说了这么多,大家应该对这个 HDFS 有一个清晰的认识了吧?说白了,就是一个文件系统,但是与我们普通的文件系统有很多不同。比如:多副本,分布式,自动备份等等。

有人会问了,Hadoop 不是凉了吗?Spark, Flink 才是未来。O__O “…

这样说是不全面的,带有全盘否定的眼光。我们常说的 Hadoop 是指 HDFS + MapReduce + Yarn ,其中 HDFS 和 Yarn 在如今的流式计算中也发挥着重要的作用,后面会提到。事实上有很多离线数仓都是使用 Hive 跑在 MapReduce 计算框架之上的。抓住技术的发展趋势没错,但是作为初学者,学习思想不会错,对比每个框架的架构思想,你会发现,不管是宝刀未老的 Hadoop ,还是站在巨人肩膀上的 Flink, 都是基于分布式的思想,在 CAP 之间权衡,为我们的大数据提供更快速的算力,为我们的数据提供更可靠的港湾。

进入正题。

HDFS 是什么

它是一个 分布式文件存储系统, 全称是 Hadoop Distributed File System 。HDFS is built using the Java language 为什么会出现这个呢?想象一个场景,数据随着业务的增长飞快的积累,达到了PB甚至更大的量级,这时候受网络带宽和单机节点的资源限制的影响,海量的数据无法进行存储,如何存储,万一数据丢了怎么办?这一系列问题,在 HDFS 中都将迎刃而解。 HDFS 就是解决海量数据的存储问题 。百度网盘就是一个现实的例子,它的成功离不开 分布式存储技术。

HDFS 的优缺点

优点:

  • 处理海量数据,TB , PB …
  • 支持处理百万规模以上的文件数量, 10k+节点
  • 适合批处理 移动计算而非数据,数据位置暴露给计算框架
  • 可构建在廉价机器上
  • 可靠性高,多个副本
  • 自动创建多个副本,副本丢失后自动恢复, 高容错性

缺点:

  • 不支持毫秒级别
  • 吞吐量达但受限于延迟
  • 不允许修改文件(其实本身支持,但不这么做,为了性能)

当然上面不是我瞎编出来的,下面是官方的说明,请对号入座。

HDFS 的组成

下面来说一下 HDFS 包含的两个大的角色: NameNode 和 DataNode。了解 web 系统结构的小伙伴一定知道主备架构,master/slave 这样的设计。没错,HDFS 的 NameNode 和 DataNode 就是 master 和 slave 的关系。

通过上面这张图也可以看出:

NameNode 主要负责管理 元数据 信息,通过管理命名空间并接受客户端的读写请求。NameNode 既然管理命名空间,就意味着管理打开、关闭、重命名文件或目录等命令,同时也负责管理 blocks 和 DataNode 节点的映射管理。

DataNode 上面存储着一个个的 Block 块,那么他就会响应客户端的读写请求,同时负责执行来自 NameNode 的 block 的创建、删除、复制等等命令。

我们的 NameNode 只负责元数据的管理,主要是管理工作。数据其实上是客户端直接通过 DataNode 流入流出的、想一想,这样的设计有什么好处呢?当我们数据请求很多时,我们的 NameNode 是没有什么压力的,全部的压力都在 DataNode 上面,我们只需要水平扩展数据节点就可以提高整个集群的吞吐量了。

NameNode 主要干这些:

  • 接受客户端的读、写请求,注意这里不是说数据通过 NameNOde 流入流出。
  • 接收 DateNode 汇报 block 列表
  • 保存元数据,元数据是基于内存的。数据包括文件的大小,归属,偏移量列表等
  • block 的位置信息,在启动的时候上报给 NN,并且动态更新。一般是3秒一次

DataNode 主要做这些: 就是用来存储数据的。逻辑上分为各个block 块

Data 副本

因为数据被切分为 Blocks 之后,副本需要分散到集群里面,所以下面和这个放置策略很有用。(前提是你的集群配置了机架信息),这个副本数默认是 3 ,我们可以自己自定义,但是不能超过 DataNode 节点的个数,因为 NameNode 不允许 DataNode 的一个节点上有多个相同的副本。

  • 第一个副本,如果在集群内部会放到上传的这台服务器的 DN 上。如果是集群外,则会随机找一个空闲的机器。
  • 第二个副本,放置在与第一个副本 不同机架 的节点上。
  • 第三个副本,放置在与第二个副本 相同机架 的 不同 节点上。
  • 更多 副本,随机

这里也可以叫做「机架感知防止策略」

下面是官网的描述:

副本选择

依据我们上面机架感知、副本放置策略,我们客户端在拿数据的时候,是基于什么样的原则呢?这个也很好理解,就近选择,也符合我们的常识。为了减少带宽和延迟,优先选择里我们客户端最近的网络节点拿数据。下面是官方的描述:

安全模式

当启动的时候,NameNode 会进入一个特殊的模式叫做安全模式。这个时候副本是不可以复制的。NameNode 接受来自 DataNode 的心跳和 block 报告信息,后者包括该数据节点承载的数据块列表。每个数据块(block)都有一个最小的副本数,如果NameNode 检查符合条件,就说明这个数据块是安全的。上面的汇报以及检查工作完成会后,再过 30 秒,就会退出安全模式了!

通讯协议

所有 HDFS 通信协议都基于TCP/IP协议之上。 客户机 建立到 NameNode 节点计算机上可配置TCP端口的连接。它与namenode对话clientProtocol。数据节点使用数据节点协议与 NameNode 通信。远程过程调用( RPC )抽象包含客户机协议和数据节点协议。根据设计,namenode从不启动任何 rpc。相反,它只响应由数据节点或客户机发出的RPC请求。

三种故障类型

The three common types of failures are NameNode failures, DataNode failures and network partitions.

  • 网络延迟,通讯发生延迟,造成假死。
  • NameNode 元数据丢失
  • DataNode 数据块损坏

访问 HDFS 系统

  • shell
  • API
  • 浏览器

命令行,可以看这里:点我

HDFS High Availability

这里只展示基于 QJM(Quorum Journal Manager) 的HA,Active 和 Standby NameNode 通过 QJM 集群来共享 edit log 。这种方式比较优雅,可以自动的切换主备。我之前写过一篇文章就讲了 Hdfs HA 的实现原理。主要是元数据的共享和两个 NameNode 的切换。

HDFS 读流程

角色:HDFS Client , NameNode, DateNode

1,首先 HDFS 调用 FileSystem 对象的 Open 方法获取一个 DistributedFileSystem 实例;

2,DistributedFileSystem 通过 RPC协议 获取第一批 block localtions(第一批 block 块的位置), 同一个 block 和副本都会返回位置信息,这些位置信息按照 hadoop 的拓扑结构给这些位置排序,就近原则。

3.前两部会生成一个 FSDataInputStream ,该对象会被封装 DFSInputStream 对象,DFSInputStream 可以方便的管理 datanode 和 namenode 数据流。客户端调用 read 方法,DFSInputStream 最会找出离客户端最近的 datanode 并连接。

4. 数据从 datanode 源源不断的流向客户端 。这些操作对客户端来说是透明的,客户端的角度看来只

是读一个持续不断的流。

5.如果第一批 block 都读完了, DFSInputStream 就会去 namenode 拿下一批 block 的 locations,然后继续读,如果所有的块都读完,这时就会关闭掉所有的流。如果在读数据的时候, DFSInputStream 和 datanode的通讯发生异常,就会尝试正在读的 block 的排序第二近的datanode,并且会记录哪个 datanode 发生错误,剩余的blocks 读的时候就会直接跳过该 datanode。

DFSInputStream 也会 检查 block 数据校验和 ,如果发现一个坏的 block ,就会先报告到 namenode 节点,然后DFSInputStream 在其他的 datanode 上读该 block 的镜像。该设计就是客户端直接连接 datanode 来检索数据并且namenode 来负责为每一个 block 提供最优的 datanode,namenode 仅仅处理 block location 的请求,这些信息都加载在 namenode 的内存中,hdfs 通过 datanode 集群可以承受大量客户端的并发访问。

RPC 跨越了传输层和应用层。RPC 使得开发包括网络分布式多程序在内的应用程序更加容易。

HDFS的写流程

1.客户端通过调用 DistributedFileSystem 的 create 方法创建新文件。

2.DistributedFileSystem 通过 RPC 调用 namenode 去创建一个没有 blocks 关联的新文件,创建前, namenode 会做各种校验,比如文件是否存在,客户端有无权限去创建等。如果校验通过, namenode 就会记录下新文件,否则就会抛出IO异常。

3.前两步结束后,会返回 FSDataOutputStream 的对象,与读文件的时候相似,FSDataOutputStream 被封装成DFSOutputStream。 DFSOutputStream 可以协调 namenode 和 datanode。客户端开始写数据到 DFSOutputStream,DFSOutputStream 会把数

据切成一个个小的 packet,然后排成队列 data quene。

4.DataStreamer 会去处理接受 data quene,它先询问namenode 这个新的 block 最适合存储的在哪几个 datanode。

里(比如重复数是 3,那么就找到 3 个最适合的 datanode),把他们排成一个管道 pipeline 输出。DataStreamer 把packet 按队列输出到管道的第一个 datanode 中,第一个datanode 又把 packet 输出到第二个 datanode 中,以此类推。

5.DFSOutputStream 还有一个对列叫 ack quene,也是由 packet 组成等待 datanode 的收到响应,当 pipeline 中的 datanode 都表示已经收到数据的时候,这时 ack quene才会把对应的 packet 包移除掉。 如果在写的过程中某个datanode 发生错误,会采取以下几步:

  • pipeline 被关闭掉;
  • 为了防止防止丢包。ack quene 里的 packet 会同步到 data quene 里;创建新的 pipeline 管道怼到其他正常 DN上
  • 剩下的部分被写到剩下的两个正常的 datanode 中;
  • namenode 找到另外的 datanode 去创建这个块的复制。当然,这些操作对客户端来说是无感知的。

6.客户端完成写数据后调用 close 方法关闭写入流。深入 DFSOutputStream 内部原理

打开一个 DFSOutputStream 流,Client 会写数据到流内部的一个缓冲区中,然后数据被分解成多个 Packet,每个Packet 大小为 64k 字节,每个 Packet 又由一组 chunk 和这组 chunk 对应的 checksum 数据组成,默认 chunk 大小为 512字节,每个 checksum 是对 512 字节数据计算的校验和数据。

===》当 Client 写入的字节流数据达到一个 Packet 的长度,这个 Packet 会被构建出来,然后会被放到队列dataQueue 中,接着 DataStreamer 线程会不断地从dataQueue 队列中取出 Packet,发送到复制 Pipeline 中的第一个 DataNode 上,并将该 Packet 从 dataQueue 队列中移到 ackQueue 队列中。ResponseProcessor 线程接收从Datanode 发送过来的 ack,如果是一个成功的 ack,表示复制 Pipeline 中的所有 Datanode 都已经接收到这个 Packet,ResponseProcessor 线程将 packet 从队列 ackQueue 中删除。

====》 在发送过程中,如果发生错误,错误的数据节点会被移除掉,ackqueue 数据块同步到 dataqueue 中,然后重新创建一个新的 Pipeline,排除掉出错的那些 DataNode节点,接着 DataStreamer 线程继续从 dataQueue 队列中发送 Packet。

下面是 DFSOutputStream 的结构及其原理,如图所示:

注意:客户端执行 write 操作后,写完的 block 才是可见的,正在写的 block 对客户端是不可见的,只有调用 sync 方法,客户端才确保该文件的写操作已经全部完成,当客户端调用 close 方法时,会默认调用 sync 方法。是否需要手动调用取决你根据程序需要在数据健壮性和吞吐率之间的权衡。

欢迎大家持续关注我,为大家奉上大数据技术文章。

文章来源:智云一二三科技

文章标题:Hadoop 系列之 HDFS

文章地址:https://www.zhihuclub.com/185820.shtml

关于作者: 智云科技

热门文章

网站地图