Distributed File System
数据量越来越多,在一个操作系统管辖的范围存不下了,那么就分配到更多的操作系统管理的磁盘中,但是不方便管理和维护,因此迫切需要一种系统来管理多台机器上的文件,这就是分布式文件管理系统 。 是一种允许文件通过网络在多台主机上分享的文件系统,可让多机器上的多用户分享文件和存储空间。 通透性。让实际上是通过网络来访问文件的动作,由程序与用户看来,就像是访问本地的磁盘一般。 容错。即使系统中有某些节点脱机,整体来说系统仍然可以持续运作而不会有数据损失。 分布式文件管理系统很多,hdfs只是其中一种。适用于一次写入多次查询的情况,不支持并发写情况,小文件不合适。
Namenode
是整个文件系统的管理节点。它维护着整个文件系统的文件目录树,文件/目录的元信息和每个文件对应的数据块列表。接收用户的操作请求。(见源码)
意思就是说我们的文件和目录是 有一些描述信息的,比如到底是文件还是目录,他的权限,他的副本数,他的尺寸,他的创建时间,他的最后一次修改时间,他的最后一次访问时间,包括你他的属组等等,全部都是他的元数据信息,这些也是放在NameNode中的。
我们还说过在HDFS中,对文件的管理是数据块的形式,一个文件被划分成了很多的数据块,这些文件块和文件的对应关系也是在NameNode中,想象,NameNode维护了这么多的信息,那么说明它是非常重要的。我们对文件系统的操作,就是对这些东西的操作。如果你不知道这些东西,你怎么操作这个系统呢?就跟我们的window系统一样,我们也就是点来点去的,我们可以创建文件夹,创建文件,删除文件夹,删除文件,查看等等等等,这些都是对文件目录树的操作,对他们的元数据信息的操作。
它还会接收用户的操作请求,什么操作请求呢,就是我们用的那些hdfs命令 ,就是用户的操作请求。换句话说,我们在这里做的这些查看 ,创建文件夹,上传,下载,阅读等等,都是通过通过namenode来访问。
那么既然它维护这么多的信息,那么它的信息放在哪 里呢。进入hadoop目录,里面有个文件夹tmp,我们进入到tmp,里面还有俩文件夹,dfs和mapred,里面 还有3个文件夹,data,name,namesecondary,我们进入到name中,这个name文件夹 就代表及namenode存放数据的路径,里面有个current目录,进入之后,可以看到4个文件,edits,fsimage,fstime,VERSION,,这4个文件分别表示不同的含义,这4个文件中有两个最核心的文件,一个是fsimage,一个是edits,fsimage代表的是文件系统镜像,里面存放的就是维护整个文件系统的目录树需要的信息,文件/目录的元信息和每个文件对应的数据块列表。
它是相当重要的。也是是说我们整个hdfs文件系统全仰仗着fsimage管理。那么说这个文件丢了,整个hdfs文件系统也就down了,这么重要,这么办呢,我们可以做个备份。我们可以让hadoop读写数据的时候,可以同时向多个fsimage中读写,这样就有安全可言了。我们该如何去配置呢,在配置文件中可以去配置,我们进入conf文件夹,然后编辑core-site.xml,我们在文件中看到了这样一句注释<!--Put site-specific property overrides in this file-->。所以我们去源码中,找到hdfs.default.xml,它里面也有一句注释<Do not modify this file directly.Instead,copy entire that you wish to modify from this file into hdfs-site.xml and change them there.If hdfs-site.xml does not already exist,create it.>,从这两句注释可以看出来,这个配置文件原来就有,里面的值都是默认值,而在/conf目录下的配置文件只是对这个文件进行修改而已,overrides 体现了这个意思。大家会不会有这样的疑惑,系统中已经有他的配置文件,我现在呢再进行覆盖,拿系统是这么加载的呢,如果有这个疑问的话,想象Struts2那个框架,我们在项目中有一个配置文件, strust.xml,他里面有一个标签叫<package> 这个标签后面有个数据 expend,strust-default,那个配置文件在Struts2的jar中的,我们在项目中写的配置文件也是覆盖他 ,这里的意思和他是类似的。
在配置文件中找到这一项,里面${hadoop.tmp.dir}类似于el表达式,程序执行的时候会解析他,替换成值,
<property>
<name>dfs.name.dir</name>
<value>${hadoop.tmp.dir}/dfs.name,/...,/...</value>
</property>
在实际生产中,fsimage的副本最好放在不同的硬盘上
文件包括: fsimage:元数据镜像文件。存储某一时段NameNode内存元数据信息。
edits:操作日志文件。
edits存放的是操作日志文件,也就是说我们用户的操作,增删改操作。edits存这些东西的意义:我们用hdfs存放数据都是存放大数据, 大数据的传输都是很耗时的,如果我们用put命令把文件上传到hdfs 过程中,出现网络中断, 那么就会造成传输失败,那么失败,有的文件时会传一半,那么这些传了一半的文件到底是在hdfs中,被用户看到还是不应该看到,应该不能被看到吧。那么怎么样做 这个事情呢。如果正儿八经的上传成功了,用户就应该看到,这个又是怎么做的呢。所以应该考虑叫做事务的东西,事务这个词表示的就是一系列操作,要么全部成功,要么全部失败,edits就是保存用户操作事务的一个东西。举个例子,比如100G的文件,每写一个数据块,我们就在我们的这个日志文件中写一个记录。如果全部写完的话,那么最后写一个上传完毕,如果 操作失败的话,这个日志就不会出现上传完毕的那个记录。,就代表没有成功,就会,把这个事务中的操作全删掉,也就是回滚。用户就看不到了。
如果全部上传成功的话,就会让用户看到,那么我们看到的数据来自哪里,来自fsimage,不是来自edits, 但是我们用户的上传操作信息都是写在edits,那么edits中的数据这么就到了fsimage了呢,还有一个问题随着用户的上传edits会变得越来越大,如何处理edits文件越来越庞大的问题呢。是这样,edits中的文件如何转移到fsimage,他是通过另一个节点,secondarynamenode,他是干啥的,他只有一个功能,就是把namenode中edits的数据合并到fsimage中,所以他是从NameNode上下载元数据信息 (fsimage,edits),然后把二者合并,生成新的fsimage,在本地保存,并将其推送到NameNode,同时重置NameNode的edits.
为什么要用secondarynode来做,namenode自己做不行吗,是这样,我们的namenode是接受用户操作请求的,用户的操作是不能等待的,只能让他越快越好, 所以把fsimage中的信息全部存放 在内存中,意味着内存占用会越来越大,就不应该再进行合并操作,因为合并也战很大内存,否则会使内存占用非常严重,用户操作相应就变慢,所以不自己做交给secondarynode做。
也就是说我们的edits文件是定期合并到fsimage中,那么定期是什么意思,定期指的是是checkpoint,检查点,共有两个。一个是我们间隔某一段时间(3600s)的时候,我们进行合并一次,还有一个,当我们没有达到3600是,但是我们的edits文件大小超过了64M,此时也进行合并。同时也可以看出,文件大小检查点的优先级高于时间检查点。
这两个设置可以在default.core.xml文件中找到。
<property>
<name>fs.checkpoint.period</name>
<value>3600</value>
</property>
<property>
<name>fs.checkpint.size</name>
<value>64M转换</value>
</property>
fstime:保存最近一次checkpoint的时间 以上这些文件是保存在linux的文件系统中。