前面我们掌握了HDFS的基本使用,下面我们来详细分析一下HDFS深层次的内容
HDFS支持主从结构,主节点称为 NameNode ,是因为主节点上运行的有NameNode进程,NameNode支持多个,目前我们的集群中只配置了一个
从节点称为 DataNode ,是因为从节点上面运行的有DataNode进程,DataNode支持多个,目前我们的集群中有两个
HDFS中还包含一个 SecondaryNameNode 进程,这个进程从字面意思上看像是第二个NameNode的意思,其实不是,一会我们会详细分析。
在这大家可以这样理解:
公司BOSS:NameNode
秘书:SecondaryNameNode
员工:DataNode
接着看一下这张图,这就是HDFS的体系结构,这里面的TCP、RPC、HTTP表示是不同的网络通信方式,通过这张图是想加深大家对HDFS体系结构的理解,我们前面配置的集群NameNode和SecondaryNameNode进程在同一台机器上面,在这个图里面是把它们分开到多台机器中了。
那接下来我们就详细分析这里面的每一个进程。
首先是NameNode,NameNode是整个文件系统的管理节点
它主要维护着整个文件系统的文件目录树,文件/目录的信息 和 每个文件对应的数据块列表,并且还负责接收用户的操作请求
目录树:表示目录之间的层级关系,就是我们在hdfs上执行ls命令可以看到的那个目录结构信息。
文件/目录的信息:表示文件/目录的的一些基本信息,所有者 属组 修改时间 文件大小等信息
每个文件对应的数据块列表:如果一个文件太大,那么在集群中存储的时候会对文件进行切割,这个时候就类似于会给文件分成一块一块的,存储到不同机器上面。所以HDFS还要记录一下一个文件到底被分了多少块,每一块都在什么地方存储着
我们现在可以到集群的9870界面查看一下,随便找一个文件看一下,点击文件名称,可以看到Block information 但是文件太小,只有一个块 叫Block 0
我们试着上传一个大一点的文件,找一个200M左右的文件。
[root@bigdata01 hadoop-3.2.0]# cd /data/soft/ [root@bigdata01 soft]# hdfs dfs -put hadoop-3.2.0.tar.gz /
这个时候再去看 就能看到分成了多个Block块,一个文件对应有多少个Block块信息 是在namenode里面保存着的
接收用户的操作请求:其实我们在命令行使用hdfs操作的时候,是需要先和namenode通信 才能开始去操作数据的。
为什么呢?
因为文件信息都在namenode上面存储着的
namenode是非常重要的,它的这些信息最终是会存储到文件上的,那接下来我们来看一下NameNode中包含的那些文件
NameNode主要包括以下文件:
这些文件所在的路径是由hdfs-default.xml的dfs.namenode.name.dir属性控制的
hdfs-default.xml文件在哪呢?
它在hadoop-3.2.0sharehadoophdfshadoop-hdfs-3.2.0.jar中,这个文件中包含了HDFS相关的所有默认参数,咱们在配置集群的时候会修改一个hdfs-site.xml文件,hdfs-site.xml文件属于hdfs-default.xml的一个扩展,它可以覆盖掉hdfs-default.xml中同名的参数。
那我们来看一下这个文件中的dfs.namenode.name.dir属性
dfs.namenode.name.dir file://${hadoop.tmp.dir}/dfs/name Determines where on the local filesystem the DFS name node should store the name table(fsimage). If this is a comma-delimited list of directories then the name table is replicated in all of the directories, for redundancy.
这个属性的值是由hadoop.tmp.dir属性控制的,这个属性的值默认在core-default.xml文件中。大家还有没有印象,我们在修改core-site.xml的时候设置的有hadoop.tmp.dir属性的值,值是/data/hadoop_repo,所以说core-site.xml中的hadoop.tmp.dir属性会覆盖掉core-default.xml中的值
最终dfs.namenode.name.dir属性的值就是:/data/hadoop_repo/dfs/name
那我们到bigdata01节点上看一下
进入到/data/hadoop_repo/dfs/name目录下
发现这个下面会有一个current 目录,表示当前的意思,还有一个in_use.lock 这个只是一个普通文件,但是它其实有特殊的含义,你看他的文件名后缀值lock 表示是锁的意思,文件名是in_use 表示这个文件现在正在使用,不允许你再启动namenode。
当我们启动namonde的时候 会判断这个目录下是否有in_use.lock 这个相当于一把锁,如果没有的话,才可以启动成功,启动成功之后就会加一把锁, 停止的时候会把这个锁去掉
[root@bigdata01 name]# cd /data/hadoop_repo/dfs/name [root@bigdata01 name]# ll total 8 drwxr-xr-x. 2 root root 4096 Apr 8 21:31 current -rw-r--r--. 1 root root 14 Apr 8 20:30 in_use.lock [root@bigdata01 name]# cd current [root@bigdata01 current]# ll total 4152 -rw-r--r--. 1 root root 42 Apr 7 22:17 edits_0000000000000000001-0000000000000000002 -rw-r--r--. 1 root root 1048576 Apr 7 22:17 edits_0000000000000000003-0000000000000000003 -rw-r--r--. 1 root root 42 Apr 7 22:22 edits_0000000000000000004-0000000000000000005 -rw-r--r--. 1 root root 1048576 Apr 7 22:22 edits_0000000000000000006-0000000000000000006 -rw-r--r--. 1 root root 42 Apr 8 14:53 edits_0000000000000000007-0000000000000000008 -rw-r--r--. 1 root root 1644 Apr 8 15:53 edits_0000000000000000009-0000000000000000031 -rw-r--r--. 1 root root 1523 Apr 8 16:53 edits_0000000000000000032-0000000000000000051 -rw-r--r--. 1 root root 42 Apr 8 17:53 edits_0000000000000000052-0000000000000000053 -rw-r--r--. 1 root root 1048576 Apr 8 17:53 edits_0000000000000000054-0000000000000000054 -rw-r--r--. 1 root root 42 Apr 8 20:31 edits_0000000000000000055-0000000000000000056 -rw-r--r--. 1 root root 523 Apr 8 21:31 edits_0000000000000000057-0000000000000000065 -rw-r--r--. 1 root root 1048576 Apr 8 21:31 edits_inprogress_0000000000000000066 -rw-r--r--. 1 root root 652 Apr 8 20:31 fsimage_0000000000000000056 -rw-r--r--. 1 root root 62 Apr 8 20:31 fsimage_0000000000000000056.md5 -rw-r--r--. 1 root root 661 Apr 8 21:31 fsimage_0000000000000000065 -rw-r--r--. 1 root root 62 Apr 8 21:31 fsimage_0000000000000000065.md5 -rw-r--r--. 1 root root 3 Apr 8 21:31 seen_txid -rw-r--r--. 1 root root 219 Apr 8 20:30 VERSION
里面有edits文件 和fsimage文件
fsimage文件有两个文件名相同的,有一个后缀是md5 md5是一种加密算法,这个其实主要是为了做md5校验的,为了保证文件传输的过程中不出问题,相同内容的md5是一样的,所以后期如果我把这个fsimage和对应的fsimage.md5发给你 然后你根据md5对fsimage的内容进行加密,获取一个值 和fsimage.md5中的内容进行比较,如果一样,说明你接收到的文件就是完整的。
我们在网站下载一些软件的时候 也会有一些md5文件,方便验证下载的文件是否完整。
在这里可以把fsimage 拆开 fs 是文件系统 filesystem image是镜像
说明是文件系统镜像,就是给文件照了一个像,把文件的当前信息记录下来
我们可以看一下这个文件,这个文件需要使用特殊的命令进行查看
-i 输入文件 -o 输出文件
[root@bigdata01 current]# hdfs oiv -p XML -i fsimage_0000000000000000056 -o fsimage56.xml 2020-04-08 22:23:32,851 INFO offlineImageViewer.FSImageHandler: Loading 4 strings 2020-04-08 22:23:32,916 INFO namenode.FSDirectory: GLOBAL serial map: bits=29 maxEntries=536870911 2020-04-08 22:23:32,916 INFO namenode.FSDirectory: USER serial map: bits=24 maxEntries=16777215 2020-04-08 22:23:32,916 INFO namenode.FSDirectory: GROUP serial map: bits=24 maxEntries=16777215 2020-04-08 22:23:32,916 INFO namenode.FSDirectory: XATTR serial map: bits=24 maxEntries=16777215
把fsimage56.xml这个文件拉取到window上,查看比较方便
-65 1 e97acb3bd8f3befd27418996fa5d4b50bf2e17bf 498554338 1000 1005 0 1073741829 56 5 RS-10-4-1024k 1048576 DISABLED rs 10 4 2 RS-3-2-1024k 1048576 DISABLED rs 3 2 1 RS-6-3-1024k 1048576 ENABLED rs 6 3 3 RS-LEGACY-6-3-1024k 1048576 DISABLED rs-legacy 6 3 4 XOR-2-1-1024k 1048576 DISABLED xor 2 1 16395 4 16385 DIRECTORY 1586332531935 root:supergroup:0755 9223372036854775807 -1 16393 FILE LICENSE.txt 2 1586332513657 1586332513485134217728 root:supergroup:0644 1073741827 1003 150569 0 16394 FILE NOTICE.txt 2 1586332522962 1586332522814134217728 root:supergroup:0644 1073741828 1004 22125 0 16395 FILE README.txt 2 1586332531932 1586332531689134217728 root:supergroup:0644 1073741829 1005 1361 0 0 0 16385 16393 16394 16395 0 0 0 0 1 0 0
里面最外层是一个fsimage标签,看里面的inode标签,
这个inode表示是hdfs中的每一个目录或者文件信息
例如这个:
16393 FILE LICENSE.txt 2 1586332513657 1586332513485134217728 root:supergroup:0644 1073741827 1003 150569 0
id:唯一编号
type:文件类型
name:文件名称
replication:文件的副本数量
mtime:修改时间
atime:访问时间
preferredBlockSize:推荐每一个数据块的大小
permission:权限信息
blocks:包含多少数据块【文件被切成数据块】
block:内部的id表示是块id,genstamp是一个唯一编号,numBytes表示当前数据块的实际大小,storagePolicyId表示是数据的存储策略
这个文件中其实就维护了整个文件系统的文件目录树,文件/目录的元信息和每个文件对应的数据块列表,所以说fsimage中存放了hdfs最核心的数据。
下面我们来看一下edits文件,这些文件在这称之为事务文件,为什么呢?
当我们上传一个文件的时候,上传一个10G的文件,假设传到9G的时候上传失败了,这个时候就需要重新传,那hdfs怎么知道这个文件失败了呢?这个是在edits文件中记录的。
当我们上传大文件的时候,一个大文件会分为多个block,那么edits文件中就会记录这些block的上传状态,只有当全部block都上传成功了以后,这个时候edits中才会记录这个文件上传成功了,那么我们执行hdfs dfs -ls 的时候就能查到这个文件了,
所以当我们在hdfs中执行ls命令的时候,其实会查询fsimage和edits中的内容
为什么会有这两个文件呢?
首先,我们固化的一些文件内容是存储在fsimage文件中,当前正在上传的文件信息是存储在edits文件中。
这个时候我们来查看一下这个edits文件的内容,挑一个edits文件内容多一些的文件
[root@bigdata01 current]# hdfs oev -i edits_0000000000000000057-0000000000000000065 -o edits.xml
分析生成的edits.xml文件,这个地方注意,可能有的edits文件生成的edits.xml为空,需要多试几个。
这个edits.xml中可以大致看一下,里面有很多record。每一个record代表不同的操作,
例如 OP_ADD,OP_CLOSE 等等,具体挑一个实例进行分析。
OP_ADD:执行上传操作
OP_ALLOCATE_BLOCK_ID:申请block块id
OP_SET_GENSTAMP_V2:设置GENSTAMP
OP_ADD_BLOCK:添加block块
OP_CLOSE:关闭上传操作
OP_ADD 58 0 16396 /user.txt 3 1586349095694 1586349095694134217728 DFSClient_NONMAPREDUCE_-1768454371_1 192.168.182.1 true yehua supergroup 420 0 1722b83a-2dc7-4c46-baa9-9fa956b755cd 0 OP_ALLOCATE_BLOCK_ID 59 1073741830 OP_SET_GENSTAMP_V2 60 1006 OP_ADD_BLOCK 61 /user.txt 1073741830 0 1006 -2 OP_CLOSE 62 0 0 /user.txt 3 1586349096480 1586349095694134217728 false 1073741830 17 1006 yehua supergroup 420
这里面的每一个record都有一个事务id,txid,事务id是连续的,其实一个put操作会在edits文件中产生很多的record,对应的就是很多步骤,这些步骤对我们是屏蔽的。
注意了,根据我们刚才的分析,我们所有对hdfs的增删改操作都会在edits文件中留下信息,那么fsimage文件中的内容是从哪来的?
其实是这样的,edits文件会定期合并到fsimage文件中。
有同学可能有疑问了,edits文件和fsimage文件中的内容是不一样的,这怎么能是合并出来的呢?
注意,这个其实是框架去做的,在合并的时候会对edits中的内容进行转换,生成新的内容,其实edits中保存的内容是不是太细了,单单一个上传操作就分为了好几步,其实上传成功之后,我们只需要保存文件具体存储的block信息就行了把,所以在合并的时候其实是对edits中的内容进行了精简。
他们具体合并的代码我们不用太过关注,但是我们要知道是那个进程去做的这个事情,
其实就是我们之前提到的secondarynamenode
这个进程就是负责定期的把edits中的内容合并到fsimage中。他只做一件事,这是一个单独的进程,在实际工作中部署的时候,也需要部署到一个单独的节点上面。
current目录中还有一个seen_txid文件,HDFS format之后是0,它代表的是namenode里面的edits_*文件的尾数,namenode重启的时候,会按照seen_txid的数字,顺序从头跑edits_0000001~到seen_txid的数字。如果根据对应的seen_txid无法加载到对应的文件,NameNode进程将不会完成启动以保护数据一致性。
[root@bigdata01 current]# cat seen_txid 66
最后这个current目录下面还有一个VERSION文件
[root@bigdata01 current]# cat VERSION #Wed Apr 08 20:30:00 CST 2020 namespaceID=498554338 clusterID=CID-cc0792dd-a861-4a3f-9151-b0695e4c7e70 cTime=1586268855170 storageType=NAME_NODE blockpoolID=BP-1517789416-192.168.182.100-1586268855170 layoutVersion=-65
这里面显示的集群的一些信息、当重新对hdfs格式化 之后,这里面的信息会变化。
之前我们说过 在使用hdfs的时候只格式化一次,不要格式化多次,为什么呢?
一会在讲datanode的时候会详细解释、
最后做一个总结:
fsimage: 元数据镜像文件,存储某一时刻NameNode内存中的元数据信息,就类似是定时做了一个快照操作。【这里的元数据信息是指文件目录树、文件/目录的信息、每个文件对应的数据块列表】
edits: 操作日志文件【事务文件】,这里面会实时记录用户的所有操作
seen_txid: 是存放transactionId的文件,format之后是0,它代表的是namenode里面的edits_*文件的尾数,namenode重启的时候,会按照seen_txid的数字,顺序从头跑edits_0000001~到seen_txid的数字。如果根据对应的seen_txid无法加载到对应的文件,NameNode进程将不会完成启动以保护数据一致性。
VERSION:保存了集群的版本信息



