DataNode节点的数据块管理

在前面我说过,一个DataNode可以配置多个本地存储目录来存储与自己相关的数据,这些数据主要是NameNode分配给它并要它存储的文件数据块,另外,这些数据块是存储在本地存储目录的current/子目录下面的,那么DataNode就需要能对这些数据块进行管理了,而且还能够为一个数据块分配足够的存储空间。因此,HDFS专门设计了org.apache.Hadoop.hdfs.server.datanode.FSDir类,每一个FSDir实例可以管理DataNode节点的一个存储路径中文件数据块。每一个数据块的信息对应两个文件,其中一个存数据,一个存储校验信息,如在DataNode的一个存储路径中:

DataNode节点的数据块管理


     在上面的信息中,7938414676282962418是数据块的id,1002是数据块的版本号,blk_7938414676282962418存储的是该数据块的内容,blk_7938414676282962418_1002.meta存储的是该数据块的校验信息。

     对于FSDir类,它主要包含四个属性:

DataNode节点的数据块管理

dir:存储路径的子目录current/

numBlocks:存储目录当前已经存储的数据块的数量;

children:目录current/的子目录;

lastChildIdx:存储上一个数据块的子目录序号;


     为了能够根据数据块的id快速找到对应的数据块文件(说白了就是在DataNode启动时能够快速地收集所有的Block信息好向NameNode报告),任何一个存储数据块的存储目录存储的数据块数量不能超过maxBlocksPerDir。具体来说是这样的:DataNode节点会首先把文件的数据块存储到存储路径的子目录current/下;当子目录current/中已经存储了maxBlocksPerDir个数据块之后,就会在目录current/下创建maxBlocksPerDir个子目录,然后从中选择一个子目录,把数据块存储到这个子目录中;如果选择的子目录也已经存储了maxBlocksPerDir个数据块,则又在这个子目录下创建maxBlocksPerDir个子目录,从这些子目录中选一个来存储数据块,就这样一次递归下去,直到存储路径的剩余存储空间不够存储一个数据块为止。哦,对了,maxBlocksPerDir的默认值是64,但也可以通过DataNode的配置文件来设置,它对应的配置选项是dsf.datanode.numblocks。

ok,再来看看与FSDir相关联的类吧!

DataNode节点的数据块管理


     每一个数据块被抽象成了一个Block对象,它主要有三个属性,blockId表示这个数据块的标识,它在整个HDFS集群中都是唯一的,numBytes表示这个数据块的大小,generationStamp表示这个数据块最近一次修改的时间戳。DataNodeBlockInfo存放的是Block在文件系统上的信息。它保存了Block存放的卷(FSVolume),文件名和detach状态。这里有必要解释一下detach状态:我们前面分析过,系统在升级/备份是会创建一个snapshot,snapshot的文件和current里面的数据块文件和数据块元文件是通过硬链接指向了相同的内容。当我们需要改变current里面的文件时,如果不进行detach操作,那么,修改的内容会影响snapshot里的文件,这是,我们就需要将对应的硬链接解除掉。方法很简单,就是在临时文件夹里复制文件,然后将临时文件改名为current里的对应文件,这样的话,crrent里的文件就和snapshot里的文件detach了(关于数据块的detach操作,我在后面还会讲到)。这样的技术也叫copy-on-write,是一种有效提高系统性能的方法。DataNodeBlockInfo中的detachBlock方法能够对应的数据文件和元数据文件进行detach操作。上面detach操作所提到的临时文件夹就是存储路径下的detach/子目录,这个子目录和对应的current/子目录在同一父路径下。

     当有数据块到达DataNode节点时,DataNode并不是马上在current/中为这个数据块选择合适的存储目录,而是先把它存放到存储路径的tmp/子目录下,当这个数据块被DataNode节点成功接受之后,才把它移动到current/下的合适目录中。因此,FSDir主要有以下几个方法:

1.添加一个数据块到curent/下

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

转载注明出处:http://www.heiqu.com/37c5b2eab7a6bb578b9a621809ec70bf.html