hadoop -- HDFS(2)


就算世界终结,也无所谓


翻译解释

https://www.edureka.co/blog/apache-hadoop-hdfs-architecture/


前言

通过上篇介绍我们可以了解到DFS是建立在大量商用机器上的分布式文件系统,这次来讲讲其架构(HDFS Architecture)

学习:it’s high time that 是时候了


HDFS Architecture

HDFS采用主从模式(master/slave)的架构,既是一个 NameNode 为主节点,其余节点 DataNode 作为从节点,当然之后还会说到Secondly NameNode 的概念。另外,数据的存储使用预先定义好大小的块结构(block structured)分开存储在集群中的一台或多台机器中,实现的最终结果是我们能够在单台机器上访问多个 DataNode


NameNode

NameNode 作为 HDFS 的主节点,主要的作用是维护和管理当前运行在 DataNode 中的数据块(block),这样主从模式的设计,使得用户的数据永远不会存储在 NameNode 中,而只会保留在 DataNode 中

NameNode 的作用: 1. 作为主进程维护和管理 DataNode 2. 记录存储文件的信息 -- 元数据(Metadata),元数据会记录块存储的位置、文件的大小,权限等等,主要由两个文件实现关联: - FsImage: 其包含了从 NameNode 启动以来完整的刺痛命名空间状态 - EditLogs: 保留所有最近一段时间内系统中 FsImage 中所做的修改

  1. 记录发生在系统中所有元数据的的变化,比如现在你在 HDFS 上删除了一个文件,其会在 Editlog 上立马记录下来此操作
  2. 它会定期地接收来自每个 DataNode 的心跳包(heartbeat)来监控某个 DataNode 是否还活着
  3. 当发生某个 DataNode 发生问题时,NameNode 会重新选择一个新节点并将旧数据复制过去,并重新管理磁盘空间的使用和 DataNode 之间的通信

DataNode

Functions of DataNode: 1. These are slave daemons or process which runs on each slave machine. 2. The actual data is stored on DataNodes. 3. The DataNodes perform the low-level read and write requests from the file system’s clients. 4. They send heartbeats to the NameNode periodically to report the overall health of HDFS, by default, this frequency is set to 3 seconds.


Secondary NameNode

我们知道,当 DataNode 发生故障时,作为它大佬的 NameNode 会想办法解决,但是如果 NameNode 出问题了呢,这就需要 Secondary NameNode 的参与了

值得一提的是,Secondary NameNode 并非起到后备支援的作用,它跟主 NameNode 是同时作为 deamon 运行的

Functions of Secondary NameNode: 1. The Secondary NameNode is one which constantly reads all the file systems and metadata from the RAM of the NameNode and writes it into the hard disk or the file system. 2. It is responsible for combining the EditLogs with FsImage from the NameNode. 3. It downloads the EditLogs from the NameNode at regular intervals and applies to FsImage. The new FsImage is copied back to the NameNode, which is used whenever the NameNode is started the next time.


Blocks

通常来说,文件系统的文件也是以块的形式来存放的,不过在 HDFS 中存放在了不同的位置而已,默认块的大小在 Hadoop 2.0 中时 128M,Hadoop 1.0 中为 64 M

上图所显示的,当我们有一个 514M 的文件时,它会被分成 4 个 128M 和 1 个 2M 大小的块存储在同一个或者不同的 DataNode 中


Replication Management

既然已经了解到了HDFS的最小存储单位 -- 块(block),那么接下来就需要了解的是块是怎样存储在 HDFS 中的

在 HDFS 中,每个 block 由系统规定的 replication factor = 3(可以自行配置)来复制3份存储在不同的 dataNode 中,从而达到很高的容错性(fault tolerance)

由图片可以看出,在默认设置下,每一个 block 都被复制了三份放在了不同的 dataNode 中,这样即使单个节点发生了错误,也不会影响系统的正常运行

另外,NameNode 会定时查看 block 的情况从而可以改变 replication factor 的稳定,所以说,如果有需要的话,NameNode 可以减少或增多 block 复制的份数


Rack Awareness

关于 HDFS 是怎样放置复制块的,还有一个新的概念,机架感知(Rack Awareness)

首先,我们应该知道机架的概念,顾名思义,机架可以理解为放置了 n 部机器的架子,我们将其定位为一个新的单元来称呼

现在,就是算法的问题了,机架感应算法就是解决复制快该怎样放置的问题,我们仍旧使用默认的 3 份复制,机架感应算法指的是第一份备份会被存储在本地的机架中,而其他两份复制存储在另外的机架上,就像上图指示的那样,如果我们的备份多的话,剩下的可以随机地存储在同一机架上的不同 DataNode 上,可以的话

很容易想到的是,以机架为单位的话,即使单个机架的机器都出问题了,也可以保证其他机架上仍存有备份使用

除此之外,以机架为单位可以增加网络性能,如上图所示,不同机架间的交流通过 core switch 来实现,相同机架的可以直接交流。显然这样写性能因为避免了很多机架间的交流而得到提高,而读性能因为使用了多个机架的带宽而得到提高


继续

了解了基本的架构,现在来继续深入了解 HDFS 是怎样读写文件的


HDFS Write Architecture

我们假设现在有一个客户端需要将一个 248M 的文件 'example.txt' 写入到 HDFS 中,使用 128M 的块的话,很显然可以分为 block(A) - 128M 和 block(B) - 120M

当需要写入文件时,系统遵循下列协议步骤: - 首先,客户端(client)会针对这两个 block 向 NameNode 发送写请求,say, Block A & Block B - 在确认客户端具有写权限之后,NameNode 会将可以存储该文件块的 DataNode 的 IP 地址返回给客户端,而这些 DataNode 的选取是根据机架感应算法随机得到的,而且,根据默认的复制份数,对每一个块会返回 3 个不同的 IP - 假设返回的 IP 集合如下: - For Block A, list A = {IP of DataNode 1, IP of DataNode 4, IP of DataNode 6} - For Block B, set B = {IP of DataNode 3, IP of DataNode 7, IP of DataNode 9}

  • 接下来将由以下的三步执行完成数据的存储和备份
    1. Set up of Pipeline
    2. Data streaming and replication
    3. Shutdown of Pipeline (Acknowledgement stage)

1. Set up of Pipel

在进行写操作之前,很显然客户端需要知道 NameNode 交付回来的 DataNode 有没有准备好接受数据,为了确认情况,客户端会通过返回来的 IP 序列分别向三个 DataNode 建立管道(Pipeline)连接,我们可以先拿 A 来进行说明:

For Block A, list A = {IP of DataNode 1, IP of DataNode 4, IP of DataNode 6}.

接下来,对于A块,客户端会执行以下步骤建立管道: - 客户端选择第一个IP -- DataNode 1 建立起 TCP/IP 连接 - 客户端会通知 DataNode 1 做好接受数据的准备,并且将要用于存储备份的地址 DataNode 4 和 DataNode 6 交付给它 - 接着 DataNode 1 会连接到 DataNode 4, 通知其做好准备,类似地也将DataNode 6 的地址给它 - 接下来,DataNode 4 只需要建立连接之后通知 DataNode 6 做好准备即可 - 连接建立到最后一个节点,准备充分的确认信息会逆着返回到起始节点 DataNode 1 中,Node1 再统一发回给客户端,确认三个节点都已经准备好接受数据 - 至此,管道才算完成了建立的过程,客户端开始进行数据备份和数据流过程

小疑问,客户端是直接还是间接地与 Node4、Node6 建立管道连接

2. Data Streaming

在管道建立之后,客户端将数据推送到管道中,值得一提的是,客户端仅仅只是将数据放到了 DataNode 1 中,接下来的复制由节点序列进行

所以,复制的步骤很容易就可以得出来:

  • 当客户端将数据写入 DataNode 1 后,DataNode 1 将连接 DataNode 4
  • 然后, DataNode 1 通过管道连接将数据推送至 DataNode 4 中完成复制
  • 类似地 DataNode 4 将数据复制到 DataNode 6 中

3. Shutdown of Pipeline or Acknowledgement stage

完成数据的存储和备份之后,确认信息依旧按照逆顺序返回,由 DataNode 1 集中返回给客户端,这里别忘了 NameNode 的存在,客户端收到确认信息之后,会告诉 NameNode,而其会进行相关 Metadata 的更新,之后客户端正式关掉管道

相同的,对于 block B,跟 A 的步骤是类似的,只是需要注意的是,A 和 B 的写入是并行的,没有先后之分

就像上图所示,A 和 B 构成了两条并行的管道,他们的执行顺序如下: - For Block A: 1A -> 2A -> 3A -> 4A - For Block B: 1B -> 2B -> 3B -> 4B -> 5B -> 6B

小疑问,为什么 datanode1 不用经过 Switch 可以直连 datanode4


HDFS Read Architecture

理解了写操作之后,读操作就好理解多了

我们同样假设客户端需要读取一个 example.txt 文件

读取的程序如下: - 客户端向 NameNode 请求有关 'example.txt' 文件的 Metadata - NameNode 将返回存储 Block A and B 的DataNode 的信息 - 客户端开始与相关的 DataNode(A--1, B--3) 建立并行连接并开始读取数据 - 当客户端读取完数据之后,两个数据块将合并成一个完整文件展示

有一点是,为了节省读延迟和带宽消耗, NameNode 返回的信息会尽可能地离客户端近点,所以返回的 DataNode 并非一定是写文件时的存储顺序的第一个 DataNode


总结