深入浅出Hadoop之HDFS

Hadoop生态系统一直是大数据领域的热点,其中包括今天要聊的HDFS,和计划以后想聊的yarn, mapreduce, spark, hive, hbase, 已经聊过的zookeeper,等等。

深入浅出Hadoop之HDFS

今天主聊HDFS,hadoop distributed file system, 起源于Google 的 GFS,只不过GFS是用c++写的,Hadoop是Doug Cutting在yahoo用Java写的。2008 年 Hadoop成为Apache top-level project。

应用

HDFS适用于什么场景呢? 非常大的文件存储,比如以G或T为单位,因为HDFS内部的block的基本单位已经是128MB。注意这里有一个小文件问题,误区是说怕1K的小文件也能占用128MB的硬盘,其实不是的,它还是占用1K硬盘,但是小文件问题的bottle neck是在name node里,因为name node要存储文件和block的相关信息在内存里,文件数量一多,name node的内存就不够了(比如,百万小文件要占用300MB 内存),当然hdfs federation能够通过sharding的方式解决name node内存不够用的问题,接下来会细说。HDFS还适用于“write once,read-many”的场景,而且它的写是append only,所以想改也没法改。如果是多次写的话,应该考虑一下cassandra(参见我的上一篇文章)。同时HDFS的文件通常只能允许single writer写入(是通过lease的方式来保证只有一个writer能够当前写某个文件)。HDFS因为只需要普通的commodity hardware而不需要昂贵的高可用硬件而被企业欢迎。HDFS不适用于需要low latency的数据访问方式,因为HDFS是拿延迟交换高throughput。

概念 Blocks

HDFS里,文件是被分割成block大小的chunk,每个block是128MB,有人会问了,为什么非要搞这么大,主要是要缩短寻道时间在总硬盘读写时间中的比例,比如寻道时间需要5 ms,而寻到时间只能占总时间0.5%的比例,那么硬盘读写时间差不多在1s左右,1s中能穿多少文件呢,如果硬盘的读写为128MB/s,那么就能传128MB,所以block大小就定义为128MB,这样可以保证硬盘操作的时间有效的应用在读写上而不是花费在寻道上。当然太大了也不行,mapreduce的map通常是以block为单位,如果block太少,mapreduce的效率会比较低。

hdfs fsck $path -files -blocks -locations

上面的命令可以用来提供文件的block信息,比如block在哪台机器,名字是什么,方便你进一步查询block的具体信息。

Namenodes and datanodes

深入浅出Hadoop之HDFS

namenode管理namespace, 管理文件系统树状结构和文件/目录的metadata,这些信息以如下方式持久化在硬盘里:namespace image 和 edit log。同时block的metadata也存放在namd node,存放于内存中。前面提到过百万小文件,会占用300MB内存的例子。block信息为什么不持久化呢,因为它会变动,系统重启的时候会从datanode那里重新构建。

name node的备份有几种方式,一种是把持久化存放于硬盘的信息既写到本地硬盘也同时写到远程NFS mount。另一种方式是运行secondary namenode,它其实并没有扮演namenode的角色,而是周期性的merge namesapce image以及edit log来防止edit log过大。它会保存一份merged namespace image,一旦primary fail了,就把NFS上的metadata copy到secondary namenode上,这样secondary就成为了新的primary。

具体过程如下图所示,edit log和fsimage都是在硬盘中,edit log就是WAL(cassandra写操作也用到了WAL的手段,WAL很流行,可以单拉出来讲一次),fsimage是check point of the filesystem metadata。写的时候先写edit log,然后update in-memory representation of filesystem metadata(用来serve读请求),图中没有画出这部分操作。

深入浅出Hadoop之HDFS

有没有更好的方法呢?上述方法没能提供HA, namenode仍然是single point of failure。新的primary需要(1)load namespace image into memory (2)replay edit log (3)从datanode那边接收足够的block reports(前文提到block信息是在内存中的)。这个过程有可能会话费30分钟或更久。client等不了啊~~

Hadoop 2提供了HA的support。namenode采用active-standby的配置方式:

namenodes使用高可用共享存储来存edit log。active每次写入都会被standby读出并synchronize到自己的内存中。

datanodes在发送block reports时会同时发给所有的name nodes,记住block mapping是在内存中。

客户端需要配置来handle namenode failover,其实就是watch zookeeper的leader election(参见我之前讲的zookeeper)

这样就不需要secondary namenode啦,standby取代了它的作用会周期性的产生check points

上面提到的共享存储主要指的是QJM(quorum journal manager),通常配置3个(当然我也见过50个node配5个journal nodes),写的时候需要满足quorum。

这样当active namenode fail时,standby可以马上扛住,因为latest edit log和 up-to-date block mapping都在内存中。

HDFS write

深入浅出Hadoop之HDFS

HDFS read

深入浅出Hadoop之HDFS

CLI Example

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/8a5f7aca49520f304d27a095501cb6b4.html