(1)一个DataNode上面的Block都是唯一的,多个DataNode可能存在相同的Block。
(2)通信场景:
1,NameNode上并不永久保存那个DataNode上有那些数据块的信息,而是通过DataNode启动时的上报,来更新NameNode上的映射表(DataNode和Block)。
2,DataNode和NameNode建立连接以后,就会不断地和NameNode保持心跳。心跳的返回其还也包含了NameNode对DataNode的一些命令。
3,DataNode当然也作为服务器接受来自客户端的访问,处理数据块读/写请求。
4,DataNode之间还会相互通信,执行数据块复制任务,同时,在客户端做写操作的时候,DataNode需要相互配合,保证写操作的一致性。
(3)DataNode本地数据,安装Hadoop的时候,我们会指定对应的数据块存放目录,当我们检查数据块存放目录目录时,我们回发现下面有个叫dfs的目录,所有的数据就存放在dfs/data里面,这个目录中还有一些其他的目录,暂时不用理会作用,深入代码之后自然会明白。
数据块文件显然保存了HDFS中的数据,数据块最大可以到64M。每个数据块文件都会有对应的数据块元数据文件。里面存放的是数据块的校验信息。下面是数据块文件名和它的元数据文件名的例子:
blk_3148782637964391313
blk_3148782637964391313_242812.meta
上面的例子中,3148782637964391313是数据块的ID号,242812是数据块的版本号,用于一致性检查。
(4)HDFS提供升级软件的机制,因为是大型分布式存储系统,所以升级工作不能一蹴而就。给与的策略是先运行升级(update)的系统一段时间,如果还不错则提交(finalize)这次升级。那么在升级的过程中,分布式系统中有些节点可能会fail,这样节点必须能够通过非易失的属性保持节点的状态,使得节点在下次启动的时候可以正常恢复,这种非易失性的属性就是磁盘目录结构。
(5)我们来看一下升级/回滚/提交时的DataNode上会发生什么(在类DataStorage中实现)。
前面我们提到过VERSION文件,它保存了一些文件系统的元信息,这个文件在系统升级时,会发生对应的变化。
升级时,NameNode会将新的版本号,通过DataNode的登录应答返回。DataNode收到以后,会将当前的数据块文件目录改名,从current改名为previous.tmp,建立一个snapshot,然后重建current目录。重建包括重建VERSION文件,重建对应的子目录,然后建立数据块文件和数据块元数据文件到previous.tmp的硬连接。建立硬连接意味着在系统中只保留一份数据块文件和数据块元数据文件,current和previous.tmp中的相应文件,在存储中,只保留一份。当所有的这些工作完成以后,会在current里写入新的VERSION文件,并将previous.tmp目录改名为previous,完成升级。
了解了升级的过程以后,回滚就相对简单。因为说有的旧版本信息都保存在previous目录里。回滚首先将current目录改名为removed.tmp,然后将previous目录改名为current,最后删除removed.tmp目录。
提交的过程,就是将上面的previous目录改名为finalized.tmp,然后启动一个线程,将该目录删除。