相对于HDFS的HA方案(在namenode里面建立映射表,为了防止namenode挂掉,所有一般会有两个namenode:namenode active 和 namenode standby。只有active对外提供服务。)这种设计的吞吐量不会很大,对于数据存储很频繁的系统,namenode的io速度会是系统瓶颈,再者 HDFS 的 Federation 方案(有多个namenode,分别负责几个datanode。类似于美国的联邦机制)不够灵活,本质上每个联邦的namenode都存在单点故障。除非将 HA 方案和 Federation 方案结合使用,但是系统灵活性不大,运维复杂。
而NDFS 的 HA 方案是多 namenode(indexnode),多datanode,datanode 通过 zookeeper(由Paxos/Raft支撑,不会有单点故障)发现 namenode 并向namenode更新索引,所有namenode均对外提供服务,通过LoadBalance去确定要访问的 namenode,有效提供了系统的吞吐量以及避免了单点故障。 所有datanode均为平级,只存在逻辑主备关系,所有属于同一个volume的多个datanode也均可对外提供服务,也是由LoadBalance指定。 增加了系统的灵活性,降低了运维复杂度。这种两层的负载均衡有效的提高了系统的吞吐量。
文件数 | 数据块数 | 内存占用
- | :-: | -: 3000万 | 3000万| 约12G,块管理 ≈ 7.8G,包括全部块副本信息,目录树 ≈ 4.3G,目录层次结构,包含文件块列表信息 10亿 | 10亿 | 约380G,块管理 ≈ 240GB,目录树 ≈ 140GB
文件数 | 数据块数 | 内存占用
- | :-: | -: 3000万 | 3000万| 约1G,索引树 ≈ 1G,只包含文件存在节点位置 10亿 | 10亿 | 约32G,索引树 ≈ 32G,只包含文件存在节点位置
而且在小文件居多的情况下,这种问题更加严重,但是Hadoop目前还没有一个系统级的通用的解决HDFS小文件问题的方案。它自带的三种方案,包括Hadoop Archive,Sequence file和CombineFileInputFormat,均需要用户根据自己的需要编写程序解决小文件问题。
而NDFS则将索引分散到各个 datanode ,由 namenode 索引到 datanode ,再由 datanode 索引到文件块,这种分布式的二级索引方式是 namenode 内存占用量有效降低的本源。
HDFS 由 namenode 规划储存路径,当小文件居多时这种方式占用较多的namenode的计算资源(要规划存储位置),对于在一个存储集群中,将规划存储位置的任务给相对于datanode要少很多的namenode显然是不合适的。
而 NDFS 由于其独特的数据块定义,使得可以由 datanode 规划存储位置,这种设计也使得NDFS的文件块可在脱离NDFS文件系统的时候也可以读取文件块内文件,也使得NDFS可以在datanode上建立文件索引,由datanode承担一部分索引任务,有效的降低的namenode的内存压力,计算压力,这部分将在后面详述。
共同优势,使用块存储。将零散小文件压缩成块连续储存的方式相对于直接将零散小文件离散存储的方式,能有效的降低磁盘寻道时间。如果数据块设置过少,那需要读取的数据块就比较多,由于数据块在硬盘上非连续存储,普通硬盘因为需要移动磁头,所以随机寻址较慢,读越多的数据块(例如常规的文件存储)就增大了总的硬盘寻道时间。当硬盘寻道时间比io时间还要长的多时,那么硬盘寻道时间就成了系统的一个瓶颈。合适的块大小有助于减少硬盘寻道时间,提高系统吞吐量。一个很明显的例子:
文件块头ChunkHeader占128字节,其中文件块版本version占32字节,文件块uuid占32字节,文件块中文件数量fileCount占4字节,chainHash占32字节(用来做防篡改校验),为后续预留headerUnknown 占28字节。文件头示例:
文件块数据部分ChunkData占64MByte/128MByte/256MByte/... 默认64MByte,该部分存储文件源数据,或文件压缩数据连续存储,默认使用Google Snappy压缩。示例:
{
chunkName : String
fileName : String
fileType : String
index : Integer
fileHash : String
fileSize : Integer
compressionAlgorithm : String
compressionSize : Integer
chainHash : String
del : Boolean
lastMdfTime : Long
createTime : Long
}