HDFS体系结构:(Distributed File System)
分布式系统的大概图
服务器越来越多,客户端对服务器的管理就会越来越复杂,客户端如果是我们用户,就要去记住大量的ip.
对用户而言访问透明的就是分布式文件系统.
分布式文件系统最大的特点:数据存储在多台机器上,但是对用户透明.
为什么要出现分布式文件系统?
数据量越来越大,在一台机器上存不下,就放到多台机器上存储,但是不方便管理,我们用户就必须要知道是那台服务器管理的哪些数据,数据丢失等乱七八糟的问题,迫切需要一种文件系统,对我们来说是透明的,这就出现了分布式文件系统,它会把数据存储在多台机器上,但是对用户而言不需要担心数据存储在哪台机器上,就认为存在一台机器上.
类似于我们java中面向对象中的封装,方法体现类的行为,属性体现类的状态,我们在进行系统设计的时候,尽量考虑这种封闭.
分布式文件系统,对外用户感觉就是一个存储管理的一个系统,实际内部,把数据分散在多台机器上进行存储.
数据分散在多台机器上,用户还感觉不到,说明有一个中间层,中间屏蔽了用户看到的东西,和实际存储的东西,准确的说是它的一个namespace(命名空间)的问题.
分布式文件系统的特点:
(1)hdfs中有一层结构,把外部客户端看到的文件系统逻辑结构与真正数据存储的物理结构,解耦了.
数据具体存储在哪些机器上,就由我们hdfs分布式文件系统管理的.如果我们的数据存储在很多节点上,环境又是不稳定的,系统还需要解决一些故障产生之后对用户而言有一个故障的恢复,或者说故障管理的工作.这个工作实际上是通过备份来实现的.
(2)分布式文件系统不限于hdfs一种,hdfs只是其中一种,hdfs文件系统它是hadoop领域的,适用时适用于一次写入多次查询,不提供修改,如果上传的数据上传错误,删除,再次上传一次即可.
(3)不支持并发写情况,小文件不合适.
HDFS的体系结构包括三部分:
1.NameNode:
(1)只占有一个机器,是整个文件系统的管理节点.维护着整个文件系统的文件目录树,文件/目录的元信息和文件对应的数据块列表.接收用户的请求.
数据块:文件在上传之后,会把一个大的文件拆成很多的小部分来存储,每一个小部分就叫做一个数据块.
一个分布式文件系统中,有很多的从节点DataNode专门用来存放数据的,有一个主节点叫NameNode负责对这些从节点的管理工作的.
如果我们进行文件夹的操作(mkdir,rmr,ls,lsr),只需要和NameNode通信就可了,因为NameNode它就管理着这些信息.
如果我们进行的是文件上传的操作,它会通过NameNode,再把数据上传到DataNode中去.先将文件存储的目录结构存储在NameNode中去,然后客户端再把数据直接上传到DataNode这里面.
对于大数据,并不是一股脑的全放到某一个DataNode上,NameNode会把数据分散成小块进行存储.
把大数据分散成小块存储的好处:
空间利用率上去了,传输数据时,某一个block传输失败,再次重新上传的时候只需要在多传一个block大小就可以了,从我们作为管理的角度讲,非常易于管理和维护的.
用户不需要管分成了多少份,怎么存储,hdfs帮用户管理,用户只需要使用的时候使用就可以了.
用户向DataNode上面进行读和写的时候是一个block,一个block进行读和写的,读写的时候要先和NameNode通信,然后再和DataNode通信.
(2)核心数据包括:
<1>fsimage:FileSystem元数据的镜像,前边说的重要信息都是存放在fsimage中的,它如果丢了就代表集群废了,所以我们要给fsimage做备份,在hdfs-default.xml中将dfs.name.dir的值存储改为使用","分割的多个目录列表,目的是冗余,冗余的目的是备份,也就是安全.(这也是解决hadoop1的单点问题的一种方式).单点问题也叫高可靠HA,数据如果放在一块硬盘上,硬盘如果坏了还是不行,所以数据应该最好放在多块硬盘上,如果服务器坏了,我们可以通过映射硬盘,把另一台服务器上的 硬盘映射到这台服务器上,相当于它的一个目录,这样也可以 Linux NFS:加入有一个hadoop2磁盘的路径,我们可以映射hadoop1上,映射过来的目录就好像hadoop1其他的目录使用一样.
<2>edits:保存操作日志
<3>fstime:保存最近一次checkpoint的时间.
fsimage,edits,fsime存放在linux本地磁盘的位置: hadoop/tmp/dfs/name/current
2.DataNode:
<1>提供真实文件数据的存储服务.
文件块(block):
是hdfs进行数据存储的最基本的单位.HDFS默认block的大小是64MB.可以在conf/hdfs-site.xml文件中添加dfs.block.size覆盖文件hdfs-default.xml中的dfs.block.szie值得大小.
为什么是64MB:
如果是63MB,数据在二进制上管理不方便,默认的是64MB,如果一个文件就10个G,那我们还用默认值就好了
<2>Replication(数据存储的时候,存储了多少份):
多副本,默认是3个,可以在conf/hdfs-site.xml中添加dfs.replication的值覆盖hdfs-default.xml中的dfs.replication.
文件中存储多份,就是为了数据的安全性.因为数据存储的时候,它是存在于网络上,所有网络是不稳定的,如果网络断了,我们还是可以通过副本来获取数据.
我们hadoop文件block块是存放在linux本地磁盘hadoop/tmp/dfs/data,下面的current文件夹存放我们所有的块.
默认配置文件hdfs-default.xml中dfs.data.dir决定了hdfs block块存储的位置(采用以逗号分隔的多目录存储可以解决单点问题).
如果一个文件超过64MB,按64MB划分,小于64MB,就是实际大小,而不是64MB
3.SecondaryNameNode:
HA的一个解决方案之一,不支持热备,配置即可.只做一件事,就是从NameNode上下载元数据信息(fsimage,edits),在SecondaryNameNode中合并,合并完成之后,生成一个新的fsimage,然后上传到NameNode中,同时重置NameNode中的Edits
什么情况下SecondaryNameNode会进行合并:
触发合并ecits分为时间触发和大小触发,在hdfs-default.xml中查看fs.checkpoint.period和fs.checkpoint.size中的值,触发时机中大小是优先的
SecondaryNameNode一旦开始合并,就不能往edits中写数据,转为往edits.new中写数据
SecondaryNameNode合并的过程:
NameNode单点问题:一个节点宕了,那就等于废了.
(1)使用dfs.name.dir的多目录保存数据.(最经济,简单,方便)
(2)使用SecondaryNameNode
(3)使用avatarnode,好处是第三方,可以保证集群的安全性,缺点是只能进行一种简单的切换,要想切过去可以,要想切回来,就切不回来了.
(1),(3)可以完全保证数据的准确,(2)不能保证数据的完全准确,因为在合并的时候,有一部分还没合并,这部分数据在SecondaryNameNode是不存在的,所以还是会丢,当然,丢一点总比全丢了好很多了.
执行HDFS的格式化时发生了什么事情?
(1)是NameNode创建自己的目录结构,和DataNode无关.因为我们只是上传数据,没有实际数据,DataNode根本就不发生作用.
在目录hadoop/tmp/dfs/name/current产生一个文件VERSION,VERSION中包含namespaceID是我们格式化时随机生成的,在NameNode所在节点和SecondaryNameNode所在节点上都有这个VERSION,这两个VERSION中的namespaceID必须保证一致,这样才能够保证他们是一体的,如果namespaceID不一样,结果就是集群不能用了.
在格式化时不能够多次话原因也是在这里.当我们格式化之后上传数据,在DataNode上差生的namespaceID是一个值,当进行格式化时,NameNode创建自己的目录结构,它改了,DataNode没有改,两边的namespaceID不一致,所以就不能存储数据了.
因多次格式化导致的问题,可以尝试把namespaceID改成完全一样就可以了.
学习中使用到的一个linux命令:
ls -lh linux路径:以M为单位显示文件的信息