HDFS之namenode与datanode理解

一、HDFS集群

  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 为此提供两种机制。

  • 第一种机制是备份那些组成文件系统元数据持久状态的文件。Hadoop可以通过配置使namenode在多个文件系统上保存元数据的持久状态。这些写操作是实时同步的,且是原子操作。一般的配置是,将持久状态写入本地磁盘的同时,写入一个远程挂载的网络文件系统(NFS)。
  • 另一种可行的方法是运行一个辅助namenode,但它不能被用作namenode。这个辅助namenode的重要作用是定期合并编辑日志与命名空间镜像,以防止编辑日志过大。这个辅助namenode一般在另一台单独的物理计算机上运行,因为它需要占用大量CPU时间,并且需要与namenode一样多的内存来执行合并操作。它会保存合并后的命名空间镜像的副本,并在namenode 发生故障时启用。但是,辅助namenode保存的状态总是滞后于主节点,所以在主节点全部失效时,难免会丢失部分数据。在这种情况下,一般把存储在 NFS上的namenode元数据复制到辅助namenode并作为新的主namenode 运行。

二、namenode

  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>
    <!--这个配置是将hadoop的临时目录改成自定义的目录下-->
    <name>hadoop.tmp.dir</name>
    <value>/opt/module/hadoop-2.6.5/data/tmp</value>
</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
  • layoutVersion是一个负整数,描述HDFS持久性数据结构的版本,但是改版本号与Hadoop发布的包的版本无关。只要
    布局变更,版本号就会递减。
  • namespaceID是文件系统命名空间的唯一标识符,是在namenode首次格式化时创建的。
  • clusterID是将HDFS集群作为一个整体赋予的唯一标识符,当一个集群拥有多个namenode时,数值相同。
  • blockpoolID是数据块池的唯一标识符,数据块池中包含由一个namenode管理的命名空间中的所有文件。
  • cTime属性标记了namenode存储系统的创建时间。对于刚刚格式化的文件系统,这个属性值为0,但是文件系统升级后,改值会更新到新的时间戳。
  • storageType属性说明该存储目录包含的是namenode的数据结构。

in_use_lock文件是一个锁文件,namenode使用该文件为存储目录加锁。可以避免其他namenode实例同时使用同一个存储目录的情况。

文件系统映像和编辑日志

文件系统客户端执行写操作时,这些食物首先被记录到编辑日志中。namenode在内存中维护文件系统的元数据;当编辑日志被修改时,相关元数据信息也同步更新。内存中的元数据可以支持客户端的读请求。

  • 编辑日志(edits_xxx)在概念上是单体的,但是它在磁盘的体现是多个文件,每个文件被称为一个“段”,名称由前缀edits及后缀组成,后缀指出该文件所包含的事务id。任一时刻只有一个文件处于打开可写状态(表现为:edits_inprogress_xxx开头),每个事务完成之后,且在客户端发送成功代码之前,文件都需要更新和同步。当namenode向多个目录写数据时,只有在所有写操作都更新并同步到每个副本之后方可返回成功代码。

  • 文件系统映像(fsimage_xxx)都是文件系统元数据的一个完整的永久性检查点,并非每一个写操作都会更新该文件,因为fsimage是一个大型文件,如果频繁的读写会使系统运行缓慢。但是这个特性不会降低系统的恢复能力,如果namenode发生故障,还是需要将最近的fsimage文件读入内存来重构元数据的最近状态,再从相关点开始向前执行编辑日志中记录的每个事务。

这里写图片描述

因为编辑日志和映像文件需要合并,而在同一namenode来执行合并操作会耗费大量内存和计算能力,所以一般合并操作会在另一台机器上(SecondaryNamenode),即辅助节点,使用辅助节点来创建检查点:

  1. 辅助namenode请求主namenode停止使用正在进行的edits文件,这样新的编辑操作记录到一个新文件中,主namenode还会更新所有存储目录中的seen_txid文件。
  2. 辅助namenode从主namenode获取最近的fsimage和edits文件(使用HTTP GET)
  3. 辅助namenode将fsimage文件载入内存,逐一执行edits文件中的事务,创建新的合并后的fsimage文件
  4. 辅助namenode将新的fsimage文件发送回主namenode(使用HTTP PUT),主namenode将其保存为临时的..chkpoint文件。
  5. 主namenode重新命名临时的fsimage文件,便于日后使用。

辅助检查点的触发条件一般受两个配置参数控制。默认情况下,

  • 辅助namenode每隔一小时创建检查点
  • 从上一检查点开始编辑日志的大小已经达到100万个事务

可以使用以下配置进行更改:
hdfs-site.xml

<property>
  <name>dfs.namenode.checkpoint.period</name>
      <value>3600</value> #单位:秒
  <description>The number of seconds between two periodic checkpoints.
  </description>
</property>
<property>
  <name>dfs.namenode.checkpoint.txns</name>
  <value>1000000</value> # edits事务数量
  <description>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.
  </description>
</property>

安全模式

  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

<property>
    <name>dfs.namenode.name.dir</name>
<value>file:///${hadoop.tmp.dir}/dfs/name1,file:///${hadoop.tmp.dir}/dfs/name2</value>
</property>

三、datanode

工作机制

  • 一个数据块在datanode上以文件形式存储在磁盘上,包括两个文件,一个是数据本身,一个是元数据包括数据块的长度,块数据的校验和,以及时间戳。
  • DataNode启动后向namenode注册,通过后,周期性(1小时)的向namenode上报所有的块信息。
  • 心跳是每3秒一次,心跳返回结果带有namenode给该datanode的命令如复制块数据到另一台机器,或删除某个数据块。如果超过10分钟没有收到某个datanode的心跳,则认为该节点不可用。
  • 集群运行中可以安全加入和退出一些机器

数据完整性

  1. 当DataNode读取block的时候,它会计算checksum
  2. 如果计算后的checksum,与block创建时值不一样,说明block已经损坏。
  3. client读取其他DataNode上的block.
  4. datanode在其文件创建后周期验证checksum

掉线时限参数设置

    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-interval</name>
    <value>300000</value>
</property>
<property>
    <name> dfs.heartbeat.interval </name>
    <value>3</value>
</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

解释:

  • storageID:存储id号
  • clusterID集群id,全局唯一
  • cTime属性标记了datanode存储系统的创建时间,对于刚刚格式化的存储系统,这个属性为0;但是在文件系统升级之后,该值会更新到新的时间戳。
  • datanodeUuid:datanode的唯一识别码
  • storageType:存储类型
  • layoutVersion是一个负整数。通常只有HDFS增加新特性时才会更新这个版本号。

查看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

解释:

  • namespaceID:是datanode首次访问namenode的时候从namenode处获取的storageID对每个datanode来说是唯一的(但对于单个datanode中所有存储目录来说则是相同的),namenode可用这个属性来区分不同datanode。
  • cTime属性标记了datanode存储系统的创建时间,对于刚刚格式化的存储系统,这个属性为0;但是在文件系统升级之后,该值会更新到新的时间戳。
  • blockpoolID:一个block pool id标识一个block pool,并且是跨集群的全局唯一。当一个新的Namespace被创建的时候(format过程的一部分)会创建并持久化一个唯一ID。在创建过程构建全局唯一的BlockPoolID比人为的配置更可靠一些。NN将BlockPoolID持久化到磁盘中,在后续的启动过程中,会再次load并使用。
  • layoutVersion是一个负整数。通常只有HDFS增加新特性时才会更新这个版本号。

增加新节点

    当集群达到瓶颈时,需要增加新的节点(这里使用虚拟机模拟)。

  • 在一台新的主机上做好准备,准备过程在我的之前的博客有:前往
  • 在namenode的hadoop目录下的etc/hadoop/下创建dfs.hosts文件,并添加主机名称(包括新增加的节点名称):
[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
  • 在namenode的hdfs-site.xml配置文件中增加dfs.hosts属性
<property>
  <name>dfs.hosts</name>
  <value>/opt/module/hadoop-2.6.5/etc/hadoop/dfs.hosts</value>
  <description>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.</description>
</property>
  • 刷新namenode
[root@hadoop001 hadoop]# hdfs dfsadmin -refreshNodes
Refresh nodes successful
  • 更新resourcemanager节点
[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
  • 在namenode的slaves文件中增加新主机名称
  • 单独命令启动新的数据节点和节点管理器
[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

删除数据节点

  • 在namenode的/opt/module/hadoop-2.6.5/etc/hadoop目录下创建dfs.hosts.exclude文件
[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
  • 在namenode的hdfs-site.xml配置文件中增加dfs.hosts.exclude属性
<property>
  <name>dfs.hosts.exclude</name>
  <value>/opt/module/hadoop-2.6.5/etc/hadoop/dfs.hosts.exclude</value>
  <description>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.</description>
</property> 
  • 刷新namenode、刷新resourcemanager
[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
  • 检查web浏览器,退役节点的状态为decommission in progress(退役中),说明数据节点正在复制块到其他节点。
    这里写图片描述
  • 等待退役节点状态为decommissioned(所有块已经复制完成),停止该节点及节点资源管理器。注意:如果副本数是3,服役的节点小于等于3,是不能退役成功的,需要修改副本数后才能退役。
    这里写图片描述
  • 停止节点的运行
[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
  • 从namenode的dfs.hosts文件中删除退役节点hadoop105
  • 刷新namenode,刷新resourcemanager
[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
  • 从namenode的slave文件中删除退役节点hadoop004
  • 如果数据不均衡,可以用命令实现集群的再平衡
  • 13
    点赞
  • 78
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值