3.1 HDFS的外部接口和架构
HDFS的架构设计与GFS有相似之处。让我们从HDFS对外提供的接口说起。
3.1.1 HDFS的外部接口
HDFS对外提供如下几个接口。
● create:如果文件不存在,则创建一个文件。
● append:以追加的方式打开文件。
● write:在文件尾部写入数据。
● hflush:将数据强制写入磁盘。
● close:关闭文件。
与GFS相比,HDFS不支持在任意位置随机写入。对于同一个文件,HDFS不支持多个写入方同时写入(后面的3.2.1节和3.3.3节将介绍HDFS如何保证唯一使用方写入)。
在HDFS 0.21版本之前,HDFS不支持append和hflush,并且HDFS的其他接口的语义与GFS的非常不同。在HDFS 0.21版本之前,使用create创建一个文件后,向文件中写入的数据,在文件关闭之前是不可见的,只有它的创建者可以看到,并且在文件关闭之后,就不能再向该文件中添加数据了。从效果上讲,这个设计类似于GFS的使用“场景1”中的“方法1”(见2.4.3节)。
在HDFS 0.21版本之后,虽然write接口还是只支持在文件尾部追加数据,但是这些数据在文件关闭之前是可见的,并且支持在文件关闭后重新打开,可以继续在文件尾部添加数据,也就是支持使用append来打开文件。如前所述,无论是使用create还是append打开文件,都不支持多个写入方同时写入。
3.1.2 HDFS的架构
HDFS的架构如图3.1所示。
图3.1 HDFS的架构(此图参考HDFS社区文档[1])
HDFS主要有如下几个架构组件。
● client(客户端)是运行在应用(application)上的代码,以SDK的形式存在。
● Namenode(NN),用于存储分布式文件系统的元数据(metadata)。
● HDFS中的文件被分成块(block)存储在Datanode(DN)中,用于存储文件数据。
在这样的架构下,读/写流程如下。
1.写流程
(1)客户端向NN发送创建请求,请求中包含文件路径和文件名。NN根据文件路径和文件名,在名字空间创建一个对象代表这个文件。
(2)客户端向三个DN发送要写入文件中的数据,每个DN收到数据后,都将数据写入本地的文件系统中,写入成功后,告知客户端写入成功。
(3)DN在成功写完一个block后,发送请求给NN,告知NN一个block写入成功,NN收到DN写入成功的信息后,记录这个block与机器之间的对应关系。
(4)客户端确认三个DN都写入成功后,本次写入成功。
(5)关闭文件。
2.读流程
(1)应用发起读操作,指定文件路径和偏移(offset)。
(2)客户端根据固定的block大小(即64MB),计算出数据在第几个block上。
(3)客户端向NN发送一个请求,请求中包含文件名和索引号,NN返回三个副本在哪三台机器上的信息。
(4)客户端向其中一个副本所在的机器发送请求,请求中包含要读取哪个block和字节范围(byte range)。
(5)DN从本地的文件系统中读取数据返回给客户端。
从上面的介绍可以看出,HDFS的读/写流程和GFS的读/写流程非常类似,这是因为它们采用了非常类似的架构。但是它们在写流程的细节上是不一样的,下面进行介绍。