HDFS集群有两类节点以管理节点-工作节点模式运行,即一个namenode(管理节点)和多个datanode(工作节点)。namenode管理文件系统的命名空间。它维护着文件系统树及整棵树内的所有文件和目录。这些信息以两个文件形式永久保存在本地磁盘上:命名空间镜像文件和编辑日志文件。namenode也记录着每个文件中各个块所在的数据节点信息,但是它并不会永久保存块的位置信息,因为这些信息会在系统启动时根据数据节点信息重建。
[root@hadoop001 current]# pwd
#namenode中命名空间镜像文件和编辑日志文件位置:
/opt/module/hadoop-2.6.5/data/tmp/dfs/name/current
[root@hadoop001 current]# ll
total 1132
# fsimage开头的文件是命名空间镜像文件,edits开头的文件是编辑日志文件
-rw-r--r--. 1 root root 14971 Aug 14 20:47 edits_0000000000000000001-0000000000000000125
-rw-r--r--. 1 root root 26458 Aug 14 21:47 edits_0000000000000000126-0000000000000000344
-rw-r--r--. 1 root root 5712 Aug 14 22:48 edits_0000000000000000345-0000000000000000386
-rw-r--r--. 1 root root 42 Aug 14 23:48 edits_0000000000000000387-0000000000000000388
-rw-r--r--. 1 root root 11851 Aug 15 00:48 edits_0000000000000000389-0000000000000000484
-rw-r--r--. 1 root root 10530 Aug 15 01:49 edits_0000000000000000485-0000000000000000566
-rw-r--r--. 1 root root 1048576 Aug 15 01:49 edits_inprogress_0000000000000000567
-rw-r--r--. 1 root root 3929 Aug 15 00:48 fsimage_0000000000000000484
-rw-r--r--. 1 root root 62 Aug 15 00:48 fsimage_0000000000000000484.md5
-rw-r--r--. 1 root root 4470 Aug 15 01:49 fsimage_0000000000000000566
-rw-r--r--. 1 root root 62 Aug 15 01:49 fsimage_0000000000000000566.md5
-rw-r--r--. 1 root root 4 Aug 15 01:49 seen_txid
-rw-r--r--. 1 root root 207 Aug 14 19:59 VERSION
客户端(client)代表用户通过与namenode和datanode交互来访问整个文件系统。客户端提供一个类似于POSIX(可移植操作系统界面)的文件系统接口,因此用户在编程时无需知道namenode和datanode也可实现其功能。
datanode是文件系统的工作节点。它们根据需要存储并检检索数据块(受客户端或namenode调度),并且定期向namenode发送它们所存储的块的列表。
没有namenode, 文件系统将无法使用。事实上,如果运行namenode 服务的机器毁坏,文件系统上所有的文件将会丟失,因为我们不知道如何根据datanode 的块重建文件。因此,对namenode实现容错非常重要,Hadoop 为此提供两种机制。
namenode的目录结构:
[root@hadoop001 name]# pwd
/opt/module/hadoop-2.6.5/data/tmp/dfs/name
[root@hadoop001 name]# tree
.
├── current
│ ├── edits_0000000000000000001-0000000000000000125
│ ├── edits_0000000000000000126-0000000000000000344
│ ├── edits_0000000000000000345-0000000000000000386
│ ├── edits_0000000000000000387-0000000000000000388
│ ├── edits_0000000000000000389-0000000000000000484
│ ├── edits_0000000000000000485-0000000000000000566
│ ├── edits_0000000000000000567-0000000000000000568
│ ├── edits_inprogress_0000000000000000569
│ ├── fsimage_0000000000000000566
│ ├── fsimage_0000000000000000566.md5
│ ├── fsimage_0000000000000000568
│ ├── fsimage_0000000000000000568.md5
│ ├── seen_txid
│ └── VERSION
└── in_use.lock
namenode的文件目录可以在core-site.xml中设置:
<property>
<name>hadoop.tmp.dirname>
<value>/opt/module/hadoop-2.6.5/data/tmpvalue>
property>
其中VERSION是一个JAVA属性文件,其中包含正在运行的HDFS的版本信息。内容如下:
[root@hadoop001 current]# vi VERSION
#Tue Aug 14 19:59:14 PDT 2018
namespaceID=672644148
clusterID=CID-c49b4913-f14f-43d2-bffd-740d6021cc3c
cTime=0
storageType=NAME_NODE
blockpoolID=BP-1958150420-192.168.170.131-1534301954910
layoutVersion=-60
in_use_lock文件是一个锁文件,namenode使用该文件为存储目录加锁。可以避免其他namenode实例同时使用同一个存储目录的情况。
文件系统客户端执行写操作时,这些食物首先被记录到编辑日志中。namenode在内存中维护文件系统的元数据;当编辑日志被修改时,相关元数据信息也同步更新。内存中的元数据可以支持客户端的读请求。
编辑日志(edits_xxx)在概念上是单体的,但是它在磁盘的体现是多个文件,每个文件被称为一个“段”,名称由前缀edits及后缀组成,后缀指出该文件所包含的事务id。任一时刻只有一个文件处于打开可写状态(表现为:edits_inprogress_xxx开头),每个事务完成之后,且在客户端发送成功代码之前,文件都需要更新和同步。当namenode向多个目录写数据时,只有在所有写操作都更新并同步到每个副本之后方可返回成功代码。
文件系统映像(fsimage_xxx)都是文件系统元数据的一个完整的永久性检查点,并非每一个写操作都会更新该文件,因为fsimage是一个大型文件,如果频繁的读写会使系统运行缓慢。但是这个特性不会降低系统的恢复能力,如果namenode发生故障,还是需要将最近的fsimage文件读入内存来重构元数据的最近状态,再从相关点开始向前执行编辑日志中记录的每个事务。
因为编辑日志和映像文件需要合并,而在同一namenode来执行合并操作会耗费大量内存和计算能力,所以一般合并操作会在另一台机器上(SecondaryNamenode),即辅助节点,使用辅助节点来创建检查点:
辅助检查点的触发条件一般受两个配置参数控制。默认情况下,
可以使用以下配置进行更改:
hdfs-site.xml
dfs.namenode.checkpoint.period
<value>3600value> #单位:秒
The number of seconds between two periodic checkpoints.
dfs.namenode.checkpoint.txns
<value>1000000value> # edits事务数量
The Secondary NameNode or CheckpointNode will create a checkpoint
of the namespace every 'dfs.namenode.checkpoint.txns' transactions, regardless
of whether 'dfs.namenode.checkpoint.period' has expired.
namenode启动时,首先将映像文件fsimage载入内存,并执行编辑日志edits中的各项编辑操作。一旦在内存中成功建立文件系统元数据的映像,则创建一个新的fsimage和空的编辑日志。在这个过程中,namenode运行在安全模式。意味着namenode的文件系统对客户端来说是只读的。
(严格来说,在安全模式下,在访问元数据可以成功,对于读文件来说,只有集群中当前datanode上的块可用时,才能读)
安全模式的命令
检查是否处于安全模式:
[root@hadoop001 name]# hdfs dfsadmin -safemode get
Safe mode is OFF
在脚本中用户希望在执行某条命令之前namenode先退出安全模式:
[root@hadoop001 name]# hdfs dfsadmin -safemode wait
立即进入安全模式:
[root@hadoop001 name]# hdfs dfsadmin -safemode enter
Safe mode is ON
离开安全模式:
[root@hadoop001 name]# hdfs dfsadmin -safemode leave
Safe mode is OFF
Namenode多目录配置
namenode的本地目录可以配置成多个,且每个目录存放内容相同,增加了可靠性。
具体配置如下:
hdfs-site.xml
dfs.namenode.name.dir
file:///${hadoop.tmp.dir}/dfs/name1,file:///${hadoop.tmp.dir}/dfs/name2
工作机制
数据完整性
掉线时限参数设置
datanode进程死亡或者网络故障造成datanode无法与namenode通信,namenode不会立即把该节点判定为死亡,要经过一段时间,这段时间暂称作超时时长。HDFS默认的超时时长为10分钟+30秒。如果定义超时时间为timeout,则超时时长的计算公式为:
timeout = 2 * dfs.namenode.heartbeat.recheck-interval + 10 * dfs.heartbeat.interval。
而默认的dfs.namenode.heartbeat.recheck-interval 大小为5分钟,dfs.heartbeat.interval默认为3秒。
需要注意的是hdfs-site.xml 配置文件中的heartbeat.recheck.interval的单位为毫秒,dfs.heartbeat.interval的单位为秒。
<property>
<name>dfs.namenode.heartbeat.recheck-intervalname>
<value>300000value>
property>
<property>
<name> dfs.heartbeat.interval name>
<value>3value>
property>
DataNode的目录结构
[root@hadoop001 data]# tree
.
├── current
│ ├── BP-1958150420-192.168.170.131-1534301954910
│ │ ├── current
│ │ │ ├── finalized
│ │ │ │ └── subdir0
│ │ │ │ └── subdir0
│ │ │ │ ├── blk_1073741825
│ │ │ │ ├── blk_1073741825_1001.meta
│ │ │ │ ├── blk_1073741826
│ │ │ │ ├── blk_1073741826_1002.meta
│ │ │ │ ├── blk_1073741833
│ │ │ │ ├── blk_1073741833_1009.meta
│ │ │ │ ├── blk_1073741834
│ │ │ │ ├── blk_1073741834_1010.meta
│ │ │ │ ├── blk_1073741836
│ │ │ │ ├── blk_1073741836_1012.meta
│ │ │ │ ├── blk_1073741837
│ │ │ │ ├── blk_1073741837_1013.meta
│ │ │ │ ├── blk_1073741838
│ │ │ │ ├── blk_1073741838_1014.meta
│ │ │ │ ├── blk_1073741839
│ │ │ │ ├── blk_1073741839_1015.meta
│ │ │ │ ├── blk_1073741846
│ │ │ │ ├── blk_1073741846_1022.meta
│ │ │ │ ├── blk_1073741847
│ │ │ │ ├── blk_1073741847_1023.meta
│ │ │ │ ├── blk_1073741848
│ │ │ │ ├── blk_1073741848_1024.meta
│ │ │ │ ├── blk_1073741849
│ │ │ │ ├── blk_1073741849_1025.meta
│ │ │ │ ├── blk_1073741850
│ │ │ │ ├── blk_1073741850_1026.meta
│ │ │ │ ├── blk_1073741859
│ │ │ │ ├── blk_1073741859_1035.meta
│ │ │ │ ├── blk_1073741860
│ │ │ │ ├── blk_1073741860_1036.meta
│ │ │ │ ├── blk_1073741861
│ │ │ │ ├── blk_1073741861_1037.meta
│ │ │ │ ├── blk_1073741870
│ │ │ │ ├── blk_1073741870_1046.meta
│ │ │ │ ├── blk_1073741871
│ │ │ │ ├── blk_1073741871_1047.meta
│ │ │ │ ├── blk_1073741872
│ │ │ │ ├── blk_1073741872_1048.meta
│ │ │ │ ├── blk_1073741873
│ │ │ │ ├── blk_1073741873_1049.meta
│ │ │ │ ├── blk_1073741874
│ │ │ │ ├── blk_1073741874_1050.meta
│ │ │ │ ├── blk_1073741881
│ │ │ │ ├── blk_1073741881_1057.meta
│ │ │ │ ├── blk_1073741882
│ │ │ │ ├── blk_1073741882_1058.meta
│ │ │ │ ├── blk_1073741883
│ │ │ │ ├── blk_1073741883_1059.meta
│ │ │ │ ├── blk_1073741884
│ │ │ │ ├── blk_1073741884_1060.meta
│ │ │ │ ├── blk_1073741891
│ │ │ │ ├── blk_1073741891_1067.meta
│ │ │ │ ├── blk_1073741892
│ │ │ │ ├── blk_1073741892_1068.meta
│ │ │ │ ├── blk_1073741893
│ │ │ │ ├── blk_1073741893_1069.meta
│ │ │ │ ├── blk_1073741894
│ │ │ │ └── blk_1073741894_1070.meta
│ │ │ ├── rbw
│ │ │ └── VERSION
│ │ ├── dncp_block_verification.log.curr
│ │ ├── dncp_block_verification.log.prev
│ │ └── tmp
│ └── VERSION
└── in_use.lock
datanode的版本:
[root@hadoop001 current]# vi VERSION
#Tue Aug 14 20:00:18 PDT 2018
storageID=DS-4bc1a0a5-8c82-417a-830d-513ffffcb51f
clusterID=CID-c49b4913-f14f-43d2-bffd-740d6021cc3c
cTime=0
datanodeUuid=af344182-a7f0-4467-9d34-9f77cba81855
storageType=DATA_NODE
layoutVersion=-56
解释:
查看BP-1958150420-192.168.170.131-1534301954910数据块的版本号:
[root@hadoop001 current]# cd BP-1958150420-192.168.170.131-1534301954910/current
[root@hadoop001 current]# vi VERSION
#Tue Aug 14 20:00:18 PDT 2018
namespaceID=672644148
cTime=0
blockpoolID=BP-1958150420-192.168.170.131-1534301954910
layoutVersion=-56
解释:
增加新节点
当集群达到瓶颈时,需要增加新的节点(这里使用虚拟机模拟)。
[root@hadoop001 hadoop]# pwd
/opt/module/hadoop-2.6.5/etc/hadoop
[root@hadoop001 hadoop]# touch dfs.hosts
[root@hadoop001 hadoop]# vim dfs.host
hadoop001
hadoop002
hadoop003
hadoop004
<property>
<name>dfs.hostsname>
/opt/module/hadoop-2.6.5/etc/hadoop/dfs.hosts
Names a file that contains a list of hosts that are
permitted to connect to the namenode. The full pathname of the file
must be specified. If the value is empty, all hosts are
permitted.
property>
[root@hadoop001 hadoop]# hdfs dfsadmin -refreshNodes
Refresh nodes successful
[root@hadoop001 hadoop]# yarn rmadmin -refreshNodes
17/06/24 14:17:11 INFO client.RMProxy: Connecting to ResourceManager at hadoop002/192.168.170.1132:8033
[root@hadoop001 hadoop-2.6.5]# sbin/hadoop-daemon.sh start datanode
starting datanode, logging to /opt/module/hadoop-2.6.5/logs/hadoop-root-datanode-hadoop004.out
[root@hadoop001 hadoop-2.6.5]# sbin/yarn-daemon.sh start nodemanager
starting nodemanager, logging to /opt/module/hadoop-2.6.5/logs/yarn-root-nodemanager-hadoop004.out
[root@hadoop001 sbin]# ./start-balancer.sh
starting balancer, logging to /opt/module/hadoop-2.6.5/logs/hadoop-root-balancer-hadoop002.out
Time Stamp
Iteration# Bytes Already Moved Bytes Left To Move Bytes Being Moved
删除数据节点
[root@hadoop001 hadoop]# pwd
/opt/module/hadoop-2.6.5/etc/hadoop
[root@hadoop001 hadoop]# touch dfs.hosts.exclude
[root@hadoop001 hadoop]# vim dfs.hosts.exclude
hadoop004
<property>
<name>dfs.hosts.excludename>
/opt/module/hadoop-2.6.5/etc/hadoop/dfs.hosts.exclude
Names a file that contains a list of hosts that are
not permitted to connect to the namenode. The full pathname of the
file must be specified. If the value is empty, no hosts are
excluded.
property>
[root@hadoop001 hadoop-2.6.5]# hdfs dfsadmin -refreshNodes
Refresh nodes successful
[root@hadoop001 hadoop-2.6.5]# yarn rmadmin -refreshNodes
17/06/24 14:55:56 INFO client.RMProxy: Connecting to ResourceManager at hadoop004/192.168.170.134:8033
[root@hadoop004 hadoop-2.6.5]# sbin/hadoop-daemon.sh stop datanode
stopping datanode
[root@hadoop004 hadoop-2.6.5]# sbin/yarn-daemon.sh stop nodemanager
stopping nodemanager
[root@hadoop001 hadoop-2.6.5]# hdfs dfsadmin -refreshNodes
Refresh nodes successful
[root@hadoop001 hadoop-2.6.5]# yarn rmadmin -refreshNodes
17/06/24 14:55:56 INFO client.RMProxy: Connecting to ResourceManager at hadoop004/192.168.170.134:8033