hdfs读写流程_Dive Deeper - 从头理解HDFS

b59a4a3ac12ea2464b768092ba4f1e7d.png

开头前先热热身

HDFS,全称是hadoop distributed file system,是Hadoop框架下的分布式的存储系统。所谓分布式存储系统就是指不再将数据和文件集中的存储在某一台机器上,而是采用分布式的方法,将存储空间扩展到多台机器上。

这种分布式文件存储系统的理论基础和业界先例来自于谷歌的GFS。而HDFS则是由Apache基金会开源实现的软件框架hadoop中的文件存储组件。也正因为Hadoop是开源的,目前市面上有很多厂商据此进行优化和更改,推出了自己的hadoop发行版(一般称为第三方发行版),主流版本包括Cloudera的CDH,Hortonworks的HDP等。本文的重点在于探究HDFS如何工作,故对这些商业故事暂且按下不表。

我们首先来讲讲HDFS这种分布式文件存储系统的愿景和目标,也就是HDFS的初心。

根据Apache公开文档,HDFS的设计理念在于:

1. 防止硬件故障。多个机器会相互备份数据文件,这样即使任何一台机器故障,也将不会影响系统运行和数据安全。

2. 流式数据访问。HDFS的设计理念是“一次写入,终身读取”。使用的场景集中在相比于及时交互,更需要批量处理和长期保存的数据上,也就是所谓的“高吞吐重于低延迟”,这也就是意味着HDFS的设想中,使用者一旦完成写入,除非是追加或是删除,已经写入的数据是一百年不会变的。

3. 大数据量。这里的大不是1G或者2G的大,而是至少100G或者1T的大。如果数据量只够塞满一个USB,请出门右转找SQLite。

4. 高移植性。HDFS以Java为基础,凡是有Java环境的机器都可以进行移植和适配(这一步是在第三方发行版中实现的,社区版Apache必须依赖linux系统)。

5. 算法总比数据容易传输。HDFS总是希望能够把一个计算程序传送到数据所在的机器上去,而不是将数据读到计算程序这里来,因为谁大谁小不是显而易见的嘛?

接下来,我们用迭代的方式了解一下HDFS的架构信息。

迭代式理解架构

第一期当然是先把权责分清楚,搞明白谁指挥谁。HDFS里有两种服务,一种是Name Node,一种是Data Node,一般来说上述两种Node每个都会单独存在于一个服务器上。Name Node不存储实际数据,只负责管理这些存储数据的Data Node,也就是Name Node会存储元数据。

d5b8050b026189eb4af933d9f2ce2653.png

第二期,我们深入一些,一个文件存储到HDFS中的时候,是如何存储的呢?首先,管理会规定一个块的大小(默认是128M),任何文件都需要被切割成这个大小的块;然后,使用者会规定一个副本数量,这个副本数量的意义在于每一个块都必须出现在【副本数量】个Data Node里面,以防止出现问题的时候没有副本;再次,Name Node作为管理者会分配节点地址,让每个块文件都有【副本数量】个节点可存。通过以上这种方式,HDFS实现了最基本的高可用功能,再也不怕单个机器故障而无法恢复数据了。

当然了,把一个文件切分成数据块,肯定会造成前面的数据块大小一致,而最后一个数据块不同的局面,这最后一个数据块也在Data Node里面也只会占据它本身大小而已。

a07daf30e50e57392dcb143e79dd7473.png

第三期就得聊聊Name Node了。作为管理者当然需要有艺术,许许多多的文件一齐涌入进来,Name Node如何保证自己的高可用?Name Node如何保证自己响应的速度够快?这两个问题的答案其实还算有些关系。Name Node里面有个文件叫fsimage,它存储了最新的元数据,包括所有的目录信息和文件信息。而Name Node管理元数据分两步,第一步是写edit log,这个日志文件会根据操作顺序记录每一个操作;第二步是在edit log足够大的时候把edit log和fsimage合并起来,形成一个新的fsimage。这个最新的fsimage就会保证出现问题的时候,我们有据可查,有址可追。

另外,任何一个数据进入HDFS的时候,Name Node都会直接在内存里计算和记录它应该去哪儿以及之后去哪儿找它,这种全部用RAM来运行的机制保证了使用者在访问Name Node的时候可以有足够快的速度得到需要的结果。

fc121f8ff651979c1e2819f2ff0ceefe.png

在edit log和fsimage合并的这件事情上,单纯的人可能会认为两者一拍即合,一眼就勾搭上了。但是成熟的人会看得更远一些:edit log和fsimage合并恐怕不是一件容易的事情吧?两者加起来的大小肯定不容小觑,Name Node内存里面本身要支持HDFS服务,怎么能顺利让两者合并呢?于是在HDFS中有了一个Checkpoint Node(古称Secondary Name Node)。这个东西并不一定需要一个单独的节点,可以部署在其它节点上面,但是肯定不能部署在Name Node同样的节点上。

4c3ccc187e49627751e46b144491898a.png

第四期的时候我们可以深入的再看看,如果作为管理者的Name Node宕机了怎么办呢?虽然有fsimage可以恢复,但是整个集群重启也需要时间,岂不是影响了线上服务?这是单点失效啊?

社区版的Hadoop1.0的时候,HDFS确实存在这个问题。但是在随后的2.0版本中,Hadoop增加了对高可用性的支持,具体来说就是增加了一个Standby Node作为Name Node的热备份,在Name Node宕机的情况下替代Name Node接管服务,处理客户端发来的请求。而保证Standby Node和Name Node可以快速切换的基础就是edit log的共享存储。以QJM(quorum journal manager)为例,这是一个专门的HDFS实现,适用于大部分HDFS部署。它会以一组日志节点(Journal Node)的服务为基础运行,每个Journal Node都有一个对外的简易RPC接口,接受两个Name Node对edit log的读写。这样一来,Standby Node就会有和主Name Node一致的变化日志,使得Standby Node可以在需要的时候进行切换。

值得一提的是,在有Standby Node的架构中,Standby Node会完成Checkpoint Node的工作,而不再需要单独部署Checkpoint Node的服务,否则会出现报错。

785f669034ac3c288b9af8df3be42528.png

第五期,也是最后一期,我们回到Data Node上来,重新审视一下多个备份这件事情。经过第四期,我们难免多心——难道备份这件事情也可以随随便便的发生吗?没什么说头讲究吗?其实不然。

在Data Node备份的时候,我们有两个可以注意的地方。一是从客户端往第一个Data Node写入的时候,客户端会把文件分成一个个的数据包,然后依次放到一个客户端的内部队列里面,一个一个的往第一个Data Node发送。当第一个Data Node收到了第一个包并写入之后,它开始往第二个Data Node重复这个过程以作备份,依次类推到第三个Data Node(假设是三备份的话,然而前面的图片实际上都是两备份)。二是假如是三备份的话,最完美的情况当然是三个Data Node分别处于三个不同的物理位置,也就是发到三个不同的机架上去。但这会带来比较大的传输成本,而如果三个Data Node都在一个物理机架上呢,又害怕整个机架掉电的风险。所以一般来说我们都会用两个机架——也就是有一个机架上会有两个Data Node,一个机架上只有一个Data Node。

616fd93bf534e11b7220e6bdfe08fb39.png

其它细节

除去以上架构信息,还有什么值得我们注意的呢?

首先,我们可能会想到,作为管理者的Name Node是如何跟作为劳工的Data Node沟通的呢?这就是心跳信号。Hadoop集群中Name Node会在启动的时候就开一个IPC Server(进程间通讯服务),而接下来每三秒(默认值),Data Node会往Name Node的IPC Server发一个心跳信号,而Name Node通过接受心跳信号确定Data Node是否仍然正常,并通过回复这个心跳信号来传达自己的指令。

7271ca0c2127067a49840a302a8dcbf4.png

其次是可以讲讲读流程。HDFS的写流程在前面的架构迭代里已经不言自明,那么读流程是什么样的呢?跟写过程一样,在客户端读取文件的时候,Name Node首先会把这个文件的起始数据块的位置给出来,而后根据这个起始数据块所存在的各Data Node和客户端的远近进行排序之后,客户端选择距离最近的那个Data Node开始用数据流的方式一个一个的读,读到数据块末尾的时候,关闭和这个Data Node的连接,再去寻找下一个数据块。

6e0a644adc449f43aedfe003045d34c5.png

第三点可以说一下Data Node之间存储数据的平衡问题。我们知道,当客户端写入文件的时候,首先要经过Name Node分配具体的Data Node地址,这一步可以很大程度上保证个Data Node之间有一个比较均衡的负载,但是假如我们在集群中新增加一个Data Node,这个新增的Data Node将会天然的比之前就存在的Data Node数据少,这个问题如何解决呢?

HDFS里面有一个balancer的工具,是用来解决这种不平衡情况的工具,其平衡过程大致如图所示。

facdf5155967825530eba8a6c0f7f789.png

最后提一下HDFS Federation。我们刚刚说到,当Hadoop集群正常运行的时候,所有的HDFS元数据其实都加载在Name Node的内存里面,这样在读写的时候速度会更快。但是相应的也会带来问题:因为每个数据块(block)都会产生元数据,都需要Name Node内存记录,那么假如Name Node内存不够了怎么办?Name Node的内存岂不是成为了整个集群的瓶颈?

为了解决这种问题,Hadoop2.X版本中引入了联邦环境。联邦环境简单来说是允许存在让多个Name Node共同工作,每个Name Node只管自己负责的数据块,多个Name Node一起工作,以提供横向扩展能力。Name Node中存在Name Space和Block Pool两个组件,其中Block Pool记录了每个Name Node负责的数据块编号,同时各Name Node之间不进行通讯,完全自治,所以叫做“联邦”。

15e6a1857e526283bfc0baf4e203c638.png

参考资料:

1. Apache Hadoop 3.2.1 官方文档

Apache Hadoop 3.2.1 - HDFS Federation​hadoop.apache.org
5eb0bd6b65798eb9737a5f44d963988d.png

2. Hadoop运行原理总结

Hadoop运行原理总结(详细) - buildings - 博客园​www.cnblogs.com
86914ac072b79ff8f694c9ec4e6375a8.png

3. Hadoop HDFS负载均衡

Hadoop HDFS负载均衡 - BYRans - 博客园​www.cnblogs.com
316bc6b2e5d227a20a934f11231dae37.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值