DateNode的功能主要分为三大类:和DFSClient的交互;和NameNode的交互;本身提供数据存储的功能。
DataNode引用了FSDataset来提供数据存储功能, FSDataset是这个存储结构的入口,对于DataNode上面所有的Block的操作都要经过FSDataset,由此管理在此DataNode上存储的block。FSDataset的类图如下:
DataStorage
DataStorage主要提供存储元信息,如文件目录,存储目录的状态转移管理,Version文件等等。
DataStorage内部有一个List<StorageDirectory>数据结构,表示此DataNode的存储目录,DataNode的存储目录可以是多个的,这样的好处是一个目录坏了不至于把整个DataNode都下线了,这样还可以在DataNode上挂载不同的文件系统,数据写入不同的文件系统。这个目录列表是在hdfs-site.xml中配置的dfs.data.dir的值。
DataStorage的重头戏是存储目录的状态转移管理,在DataNode启动的时候可以带上参数:
- FORMAT("-format"):格式化系统
- REGULAR("-regular"):正常启动
- UPGRADE("-upgrade"):升级
- ROLLBACK("-rollback"):回滚
- FINALIZE("-finalize"):提交
- IMPORT("-importCheckpoint"):从Checkpoint恢复
这样就可以做相应的操作,在做这些操作时有可能会中途失败,所以DataNode需要管理具体的状态以便在下次启动操作时可以先处理之前的异常状态,当异常状态处理不了的时候,需要抛出异常。状态转移大致如下:
图中展现出DataNode升级和回滚时的一些状态转移。
当DataNode启动时,DataStorage就会调用recoverTransitionRead方法检查dfs.data.dir配置的每个文件目录,首先分析每个目录现在的子目录的存在情况(DataStorage.analyzeStorage),返回StorageState;根据返回的StorageState会做相应的操作(DataStorage.doRecover),就是做上图展现的一系列操作。
FSDataset
FsDataset包含FSVolumeSet,FSVolumeSet包含FSVolume的数组,一般来说dfs.data.dir配置的每一个目录都对应着一个FSVolume,每个FSVolume落实到文件系统上至少包含了如下文件夹:current,tmp,detach,blocksBeingWritten目录;current目录表示当前正常block的存储目录,tmp目录表示datanode之间复制时block临时存储目录,blocksBeingWritten表示DFSClient写数据或者替换block时block临时存储目录,detach目录表示copy-on-write时候copy出来的block的存储目录,用于DFSClient append一个已有的block时使用。
current目录是一个FSDir类表示的结构,FsDir有一个FsDir的数组,表示FsDir的子目录,每个FsDir可以存储dfs.datanode.numblocks个Block,如果存不下就需要存在子FsDir中了。