Hadoop详解系列——一文读懂HDFS

目录

一、概述

二、HDFS核心设计

2.1、HDFS心跳机制

2.2、HDFS安全模式(SafeMode)

2.2.1、NameNode进入SafeMode 的方式

2.2.2、如何退出SafeMode

2.2.3 安全模式常用命令总结

2.3、副本存放策略及机架感知

2.3.1 原理

2.3.2、总结

2.4、负载均衡

 三、HDFS 工作机制

3.1、HDFS的写流程

3.1.1、流程概述

3.1.2、步骤图详解

 3.1.3、详细文字说明(大白话图解)

3.2、HDFS的读流程

3.2.1、流程概述

3.2.2、步骤图详解

3.2.3、详细文字说明

3.3、NameNode的工作机制

3.3.1、NameNode职责

3.3.2、NameNode元数据存储机制及管理

3.3.3、元数据的Checkporint

3.3.4、Checkporint的触发配置

3.3.5、Checkporint的附加作用

3.4、HDFS高可用机制

3.5、HDFS联邦集群

3.5.1、单个Namenode的HDFS架构的局限性

3.5.2、为什么要引入Federation

3.5.3、HDFS的Federation机制

3.5.4、Federation HDFS与当前HDFS的比较及改进


一、概述

HDFS集群由NameNode、DataNode、Secondary NameNode和Client组成。

NameNode是集群的管理节点,主要负责管理HDFS的文件元数据、配置副本策略、处理客户端的读写请求。

DataNode 负责集群的数据存储以及执行客户端的读写请求。

Secondary NameNode是NameNode 的辅助节点,其作用是辅助NameNode,分担NameNode的工作压力;定期合并Fsimage和Edits,并且同步给NameNode;紧急情况下,可以辅助恢复NameNode。

Client 是HDFS的客户端,和NameNode交互,获取数据的映射信息;和DataNode交互,负责数据的读写流程;同时还负责文件的切分工作,文件在上传HDFS的时候,Client会将文件切分成一个一个的Block,按顺序读到本地缓存,然后上传HDFS。

二、HDFS核心设计

2.1、HDFS心跳机制

心跳机制主要包含两方面:心跳和检查

具体流程如下:

        1、DataNode会定时向NameNode发送心跳数据包做汇报,默认是3秒发送一次;

        2、当DataNode长时间没有向NameNode发送心跳时,NameNode会启动检查机制,检查DataNode的状态

        3、当DataNode停止发送心跳时间超过默认值后,HDFS会将该DataNode节点状态改为 dead。默认超时计算规则如下

timeout = 2 * heartbeat.recheck.interval + 10 * dfs.heartbeat.interval

默认的检查时间 heartbeat.recheck.interval = 5分钟,dfs.heartbeat.interval是3秒。不过默认时间是可以修改的,在 hdfs-site.xml 文件中修改,值得注意的是在 hdfs-site.xml 中heartbeat.recheck.interval 单位是 毫秒,而dfs.heartbeat.interval单位是 秒。所以,举个例子,如果 heartbeat.recheck.interval设置为5000(毫秒),dfs.heartbeat.interval 设置为3(秒),那么总的超时时间是40秒。

<property>
    <name>heartbeat.recheck.interval</name> 
    <value>5000</value> 
</property> 
<property>
    <name>dfs.heartbeat.interval</name>
    <value>3</value> 
</property

2.2、HDFS安全模式(SafeMode)

SafeMode是NameNode的状态之一(active、standby、safeMode)

2.2.1、NameNode进入SafeMode 的方式

1、集群刚启动时

        由于HDFS集群的启动顺序是NameNode、DataNode、Secondary NameNode,所以当NameNode启动时,DataNode还没有启动,NameNode没有收到所有DataNode的心跳汇报,所以NameNode会进入安全模式。正常启动时进入SafeMode的原理如下

1 NameNode 的内存元数据中,包含文件存储目录的路径、副本数、 blockid ,及每一个 block 所在 DataNode的信息,而 fsimage 中,不包含 block 所在的 DataNode 信息
2 、当 NameNode 冷启动时,此时内存中的元数据只能从 fsimage 中加载而来,从而就没有 block 所在的DataNode信息,就会导致 NameNode 认为所有的 block 都已经丢失
3 、从而 HDFS 会自动进入安全模式
4 、伴随着每个 DataNode 启动后,会定期向 NameNode 汇报自身所持有的 blockid 信息,随着 DataNode 陆续 启动,从而陆续汇报block 信息, NameNode 就会将内存元数据中的 block 所在 DataNode 信息补全更新
5 、当 HDFS 集群中的每个文件都找到了所有 block 的位置,从而自动退出安全模式

2、当HDFS数据丢失到一定程度时

        当NameNode发现集群中的数据丢失到一定程度时(默认 0.1%),NameNode就会进入安全模式,进入安全模式后,客户端就不能再进行元数据的修改操作,只能进行元数据的查询操作。

这个丢失率是可以手动配置的。

# 默认是
dfs.safemode.threshold.pct=0.999f
# 新版本的配置方式
dfs.namenode.safemode.threshold-pct=0.999f

2.2.2、如何退出SafeMode

1、找到问题所在,进行修复(比如修复宕机的DataNode)

2、强制手动退出安全模式(但是并没有解决数据丢失问题)

注意:正常启动时候进入安全模式,不需要去理会,等集群正常启动之后,NameNode会自动退出安全模式。

2.2.3 安全模式常用命令总结

hdfs dfsadmin -safemode leave //强制NameNode退出安全模式
hdfs dfsadmin -safemode enter //进入安全模式
hdfs dfsadmin -safemode get //查看安全模式状态 
hdfs dfsadmin -safemode wait //等待,一直到安全模式结束

2.3、副本存放策略及机架感知

2.3.1 原理

首先,HDFS对文件是分块存储。每个块的副本存放一般默认是存放3份,这些副本块存储在不同的节点上,这种分块存储+副本的策略是保证HDFS可靠性和性能的关键,其原因如下:

1、文件分块之后,按照数据块来读,提高了文件随机读和并发读的效率;

2、保存若干副本到不同节点,实现可靠性的同时也提高了同一数据块并发读的效率

3、分块存储非常切合MR的任务切分的思想。在这里,副本的存放策略又是HDFS实现高可靠和高性能的关键。

HDFS采用一种 机架感知 的策略来改进数据的可靠性、可用性和网络带宽的利用率。

副本存放策略:客户端放一份,客户端所在机架别的节点存一份,其他机架的节点存一份(就近原则,网络拓扑距离),在这种情况下,数据并不是均衡的存储在所有节点上:而是三分之一的数据在一个节点(客户端节点)上,三分之二的数据在同一个机架(客户端所在机架)上,剩下的三分之一副本均匀的分布在其他的机架上。这种策略在不损害高可靠性和读取性能的情况下,提高了数据的写的性能。

2.3.2、总结

1、作用

        数据分块存储和副本的策略,是保证高可靠性和性能的关键

2、方法

        将每个文件的数据进行分块存储,每一个数据块保存多个副本,每个副本在不同的节点上。

3、存放说明

        多数情况下,HDFS默认存储三个副本,其存放策略如下:如图Block1、Block2分别表示两个数据块,Block1的三个副本分别存储在Rack1的dn1、dn2和Rack2 的dn1节点中,block2 的三个副本分别存储在 Rack1 的dn1、dn3和Rack3的 dn2中。

副本存储

4、修改副本数

        修改副本数有两种方法,一种是修改hdfs-site.xml文件,这种方法只会作用于将来上传到HDFS的文件;另一种是通过命令的方式来修改指定目录下已经存在的文件,无法对将来上传的文件进行影响。两种设置方式如下:

# 修改 hdfs-site.xml 文件
<property> 
    <name>dfs.replication</name>
    <value>2</value> 
</property>

# 命令行设置
hadoop fs -setrep -R 2 /

2.4、负载均衡

HDFS分块存储+副本策略,虽然保证了数据的高可靠性和高性能,但是也有一些弊端,就是数据分布不均匀,三分之二的数据都是集中在一个机架上,针对这种情况,HDFS提供了负载均衡的操作,只不过这个负载均衡的效果比较慢。

数据均衡需要满足以下原则:

1、数据均衡不能导致数据块减少,数据块副本丢失

2、管理员可以中止均衡进程

3、每次移动的数据量及占用的网络资源,必须是可控的

4、数据均衡过程,不能影响NameNode正常工作

HDFS负载均衡 机器容量最高的值和最低的值 差距不能超过10%

均衡命令如下:

# 默认均衡命令
sbin/start-balancer.sh 
# 指定差距
sbin/start-balancer.sh -threshold 5
sbin/start-balancer.sh -t 10%

HDFS负载均衡的命令类似于 java垃圾回收中的 System.gc()方法,不会立即响应,只会在空闲的时候进行操作。

自动均衡进行的过程是非常缓慢的,因为 HDFS集群默认balance操作不能占据太大的网络带宽,当然,这个带宽也是可以调节的。调节命令如下:

# 这里举例配置的是10M/s,默认是1M/s
hdfs dfsadmin -setBalanacerBandwidth newbandwidth
hdfs dfsadmin -setBalanacerBandwidth 10485760

 另外,也可以直接在 hdfs-site.xml中直接修改

<property>
    <name>dfs.balance.bandwidthPerSec</name> 
    <value>10485760</value> 
    <description> Specifies the maximum bandwidth that each datanode can utilize for the balancing purpose in term of the number of bytes per second. 
    </description> 
</property>

 三、HDFS 工作机制

3.1、HDFS的写流程

该机制讲述一个大文件,该如何被写入到HDFS。

3.1.1、流程概述

客户端要向HDFS写数据,首先要向NameNode通信以确认数据可以写入,并确认block写入的DataNode,然后客户端逐一将block传给对应的DataNode,并由接收到bolck的DataNode节点负责向其他DataNode复制block副本。具体流程如下:

1、使用HDFS提供的客户端client向远程的NameNode发起RPC请求。

2、NameNode检查药创建的文件是否存在,创建是否有权限进行操作,成功则会为文件创建一条记录,否则会让客户端抛出异常。

3、当客户端开始写入数据的时候,客户端会将文件分成多个 packets ,并在内部以数据队列“data queue(数据队列)”的形式管理这些pockets,并向NameNode申请blocks,获取用来存储replicas的合适的DataNode列表,列表的大小由NameNode中的replication的设定而定。

4、开始以pipeline(管道)的形式将packet写入所有的replicas中。客户端把packet以流的方式写入第一个DataNode,该DM在存储该packet之后,将其传给该pipeline中的下一个DataNode,直到最后一个DataNode。这种写数据的方式呈流水线式的形式。

5、最后一个DataNode存储成功之后,会返回一个 “ ack packet(确认队列)”,在pipeline中传递到客户端,在客户端的开发库内部维护着“ ack queue”,当成功的收到DataNode返回的 ack packet后会从 “ ack queue”中删除对应的packet。

6、如果在传输过程中,某个DataNode发生故障,那么当前的pipeline会关闭,出现故障的DataNode会从当前的pipeline中移除,剩余的block会继续在剩余的DataNode中继续以pipeline的形式传输,同时NameNode会安排一个新的DataNode到pipeline中,保持replicas的数量。

7、客户端完成数据的写入后,会对数据流调用 close()方法,关闭数据流。

扩展:

只要写入了 dfs.replication.min(最小写入成功的副本数)的副本数(默认为1),写操作就会成功,并且这个数据块可以在集群中异步复制,直到达到其目标副本数(hdf.replication的默认数是3),因为NameNode已经知道文件由哪些块组成,所以它在返回成功前只需要等待数据块进行最小量的复制。

3.1.2、步骤图详解

HDFS写数据流程图(图片出自《Hadoop权威指南》)

 3.1.3、详细文字说明(大白话图解)

1、客户端通过调用DistributedFileSystem的create方法,创建一个新的文件

2、DistributedFileSystem通过RPC(远程过程调用)调用NameNode,去创建一个没有 blocks关联的新文件。创建前NameNode会做各种校验,比如文件是否存在,客户端有无权限去创建等。如果校验通过,NameNode 就会记录下新文件,否则就会抛出IO异常。

3、前两步结束后会返回 FSDataOutputStream 的对象,和读文件的时候相似,FSDataOutputStream 被封装成 DFSOutputStreamDFSOutputStream 可以协NameNode DataNode。客户端开始写 数据到DFSOutputStreamDFSOutputStream 会把数据切成一个个小 packet,然后排成队列 data queue。

4、DataStreamer 会去处理接受 data queue,它先问询 NameNode 这个新的 block 最适合存储的在 哪几个DataNode里,比如重复数是3,那么就找到3个最适合的 DataNode,把它们排成一个 pipeline。DataStreamer packet 按队列输出到管道的第一个 DataNode 中,第一个 DataNode 又 把 packet 输出到第二个 DataNode 中,以此类推。

5 DFSOutputStream 还有一个队列叫 ack queue ,也是由 packet 组成,等待 DataNode 的收到响应,当pipeline 中的所有 DataNode 都表示已经收到的时候,这时 ack queue 才会把对应的 packet 包移除掉。
6 、客户端完成写数据后,调用 close 方法关闭写入流。
7 DataStreamer 把剩余的包都刷到 pipeline 里,然后等待 ack 信息,收到最后一个 ack 后,通知DataNode 把文件标示为已完成。

3.2、HDFS的读流程

该机制讲述是的如何从HDFS读到一个文件。

3.2.1、流程概述

客户端将要读取的文件路径发送给 NameNode NameNode 在经过校验之后获取文件的元信息(主要 是 block 的存放位置信息)返回给客户端,客户端根据返回的信息找到相应 DataNode 逐个获取文件的 block 并在客户端本地进行数据追加合并从而获得整个文件。HDFS读数据具体流程如下:
1 、使用 HDFS 提供的客户端 Client ,向远程的 NameNode 发起 RPC 请求;
2 NameNode 会视情况返回文件的全部 block 列表,对于每个 block NameNode 都会返回有该block 拷贝的 DataNode 地址;
3 、客户端 Client 会选取离客户端最近的 DataNode 来读取 block ;如果客户端本身就是 DataNode ,那么将从本地直接获取数据;
4 、读取完当前 block 的数据后,关闭当前的 DataNode 链接,并为读取下一个 block 寻找最佳的DataNode;
5 、当读完列表 block 后,且文件读取还没有结束,客户端会继续向 NameNode 获取下一批的 block 列表;
6 、读取完一个 block 都会进行 checksum 验证,如果读取 DataNode 时出现错误,客户端会通知 NameNode,然后再从下一个拥有该 block 拷贝的 DataNode 继续读

3.2.2、步骤图详解

HDFS读数据流程图(图片出自《Hadoop权威指南》)

3.2.3、详细文字说明

1 、客户端首先调用 FileSystem 对象的 open 方法打开文件,其实获取的是一个
DistributedFileSystem 的实例。
2 DistributedFileSystem 通过调用 RPC ( 远程过程调用 ) namenode 发起请求,获得文件的第一批 block 的位置信息。同一 block 按照备份数会返回多个 DataNode 的位置信息,并根据集群的网络拓扑 结构排序,距离客户端近的排在前面, 如果客户端本身就是该 DataNode ,那么它将从本地读取文件。
3 DistributedFileSystem 类返回一个 FSDataInputStream 对象给客户端,用来读取数据,该对象会被封装成 DFSInputStream 对象,该 DFSInputStream 对象管理着 datanode namenode I/O 数据流。客户端对输入端调用 read 方法, DFSInputStream 就会找出离客户端最近的 datanode 并连接datanode。
4 、在数据流中重复调用 read() 函数,直到这个块全部读完为止。 DFSInputStream 关闭和此
DataNode 的连接。接着读取下一个 block 块。这些操作对客户端来说是透明的,从客户端的角度来看只是读一个持续不断的流。每读取完一个 block 都会进行 checksum 验证,如果读取 datanode 时出现错误,客户端会通知 NameNode ,然后再从下一个拥有该 block 拷贝的 datanode 继续读。
5 、当正确读取完当前 block 的数据后,关闭当前的 DataNode 链接,并为读取下一个 block 寻找最佳的DataNode 。如果第一批 block 都读完了,且文件读取还没有结束 DFSInputStream 就会去namenode 拿下一批 block 的位置信息继续读。
6 、当客户端读取完毕数据的时候,调用 FSDataInputStream close 方法关闭掉所有的流。

3.3、NameNode的工作机制

3.3.1、NameNode职责

HDFS是主从架构,NameNode是HDFS的主节点,负责管理集群。其职责具体为以下几点:

        1、负责客户端请求(读写数据请求)的响应

        2、管理HDFS的元数据:包括命名空间、访问控制信息、文件与数据块的映射信息和数据块的存储位置等

        3、管理应用和副本存放策略

        4、管理集群数据块的负载均衡问题

3.3.2、NameNode元数据存储机制及管理

WAL Write ahead Log : 预写日志系统
在计算机科学中,预写式日志( Write-ahead logging ,缩写 WAL )是关系数据库系统中用于提供原子 性和持久性(ACID 属性中的两个)的一系列技术。在使用 WAL 的系统中,所有的修改在提交之前都要 先写入 log 文件中。
Log 文件中通常包括 redo undo 信息。这样做的目的可以通过一个例子来说明。假设一个程序在执 行某些操作的过程中机器掉电了。在重新启动时,程序可能需要知道当时执行的操作是成功了还是部分成功或者是失败了。如果使用了 WAL ,程序就可以检查 log 文件,并对突然掉电时计划执行的操作内容跟实际上执行的操作内容进行比较。在这个比较的基础上,程序就可以决定是撤销已做的操作还是继续完成已做的操作,或者是保持原样。
WAL 允许用 in-place 方式更新数据库。另一种用来实现原子更新的方法是 shadow paging ,它并不是 in-place 方式。用 in-place 方式做更新的主要优点是减少索引和块列表的修改。 ARIES WAL 系列技术 常用的算法。在文件系统中,WAL 通常称为 journaling PostgreSQL 也是用 WAL 来提供 point-intime 恢复和数据库复制特性。

NameNode 对元数据的存储采用两种存储方式:内存和磁盘

        1、内存metadata        

        在内存中存储了一份完整的元数据,包括目录树结构,以及文件和数据块和副本存储地的映射关系;为了提高读写响应。

        2、磁盘元数据

                磁盘中也存储了一份完整的元数据,为了提高数据安全性。

                磁盘中的元数据由以下几部分组成:   

                        fsimage        镜像文件
                        edits        历史元数据编辑日志
                        edits_inprogress    正在使用的编辑日志,只有一个
                        VERSION       记录元数据的版本信息
                        seen_txid   checkpoint过程中记录的上一次chekpoint的TXID

注意:磁盘元数据,存储在namenode节点的某个指定目录下,安装的时候有制定过

213
NN磁盘中的元数据信息​​​​​

上图中的磁盘元数据镜像文件fsimage_0000000000024994452

fsimage_0000000000024994452

等价于

edits_0000000000000000001-0000000000000000118

...

edits_0000000000024991477-0000000000024994452

合并之和。

也就是说

完整的元数据metadata = 最新的 fsimage_0000000000024995189 + edits_inprogress_0000000000024995190

完整的元数据metadata = 所有的edits之和(edits_001_002 + …… + edits_444_555 +

edits_inprogress_0000000000024995190

完整的元数据metadata =  内存元数据

另外存放磁盘元数据的目录中,还有一个文件: VERSION (存放 hdfs 集群的版本信息),见上图,其内容如下:
#Fri May 07 10:31:34 CST 2021
namespaceID=896744018
clusterID=CID-cfbc9ac6-8814-46d3-a713-d57b3292458f
cTime=1590433690859
storageType=NAME_NODE
blockpoolID=BP-908665078-192.168.100.191-1590433690859
layoutVersion=-64

当然,edits和fsimage文件也都有特殊的命令可以查看,命令如下

# 查看edits文件
hdfs oev -i edits_0000000000000000193-0000000000000000194 -o edits.xml
cat edits.xml

# 查看fsimage镜像文件信息
hdfs oiv -i fsimage_0000000000000000144 -p XML -o fsimage.xml 
cat fsimage.xml

3.3.3、元数据的Checkporint

每隔一段时间,secondary NameNode会将NameNode上累计的edits 和一个最新的 fsimage 文件下载到本地,并加载到内存进行合并 (这个过程称为 checkporint)

checkporint详细过程图解如下:

元数据Checkporint流程

 checkporint详细过程文字描述:

1 、周期性发送请求给 NN ,获取 fsimage edits
2 NN 收到请求后,生成一个空的 edits.new 文件
3 NM SNN 发送 fsimage edits
4 SNN fsimage 文件加载到内存,合并 edits 文件
5 snm 生成新的镜像文件 fsimage.ckpt
6 SNN 发送 fsimage.ckpt NN
7 NN fsimage.ckpt 替换 fsimage 文件,将 edits.new 重命名为 edits 文件

3.3.4、Checkporint的触发配置

##检查触发条件是否满足的频率,60秒
dfs.namenode.checkpoint.check.period=60
##以上两个参数做checkpoint操作时,secondary namenode的本地工作目录 
dfs.namenode.checkpoint.dir=file://${hadoop.tmp.dir}/dfs/namesecondary
dfs.namenode.checkpoint.edits.dir=${dfs.namenode.checkpoint.dir} 
##最大重试次数
dfs.namenode.checkpoint.max-retries=3  
##两次checkpoint之间的时间间隔3600秒 
dfs.namenode.checkpoint.period=3600
##两次checkpoint之间最大的操作记录
dfs.namenode.checkpoint.txns=1000000

3.3.5、Checkporint的附加作用

        NameNode 和 SecondaryNamenode 的工作目录存储结构完全相同,所以,当 NameNode 故障退出需要重新恢复时,可以从 SecondaryNamenode 的工作目录中将 fsimage 拷贝到 NameNode 的工作目录,以恢复 NameNode 的元数据。

3.4、HDFS高可用机制

Hadoop 2.2.0 版本之前, NameNode HDFS 集群的单点故障点,每一个集群只有一个 NameNode ,如果这个机器或者进程不可用,整个集群就无法使用,直到重启。
Secondary NameNode 。它不是 HA ,它只是阶段性的合并 edits fsimage ,以缩短集群启动的时间。 当NameNode( 以下简称 NN) 失效的时候, Secondary NN 并无法立刻提供服务, Secondary NN 甚至无 法保证数据完整性:如果NN 数据丢失的话,在上一次合并后的文件系统的改动会丢失。
NameNode 或者新重启一个 NameNode 节点 。影响 HDFS 集群不可用主要包括以下两种情况:
A :类似机器跌宕这样的意外情况将导致集群不可用,只有重启 NameNode 之后才可使用。
B :计划内的软件或硬件升级( NameNode 节点)将导致集群在短时间范围内不可用。
HDFS 的高可用性( HA High Availability )就可以解决上述问题,通过提供选择运行在同一集群中的 一个热备用的 " / " 两个冗余 NameNode ,允许在机器宕机或系统维护的时候, 快速转移到另一个 NameNode。
一个典型的 HA 集群,两个单独的机器配置为 NameNodes ,在任何时候,一个 NameNode 处于活动状态,另一个处于待机状态,活动的 NameNode 负责处理集群中所有客户端的操作,待机时仅仅作为一 个slave ,保持足够的状态,如果有必要提供一个快速的故障转移。
为了保持备用节点与活动节点状态的同步,目前的实现需要两个节点同时访问一个共享存储设备(例如 从NASNFS 挂载)到一个目录。将有可能在未来的版本中放宽此限制。
当活动节点对命名空间进行任何修改,它将把修改记录写到共享目录下的一个日志文件,备用节点会监 听这个目录,当发现更改时,它会把修改内容同步到自己的命名空间。备用节点 在故障转移时,它将 保证已经读取了所有共享目录内的更改记录,保证在发生故障前的状态 与活动节点保持完全一致。
为了提供快速的故障转移,必须保证备用节点有最新的集群中块的位置信息,为了达到这一点,
Datanode 节点需要配置两个 nameNode 的位置,同时发送块的位置信息和心跳信息到两个 nameNode。
任何时候只有一个 namenode 处于活动状态,对于 HA 集群的操作是至关重要的,否则两个节点之间的状态就会产生冲突,数据丢失或其它不正确的结果,为了达到这个目的或者所谓的 “ 裂脑场景 出现,管 理员必须为共享存储配置至少一个(fencing )方法。在宕机期间, 如果不能确定之间的活动节点已经 放弃活动状态,fencing 进程负责中断以前的活动节点编辑存储的共享访问。这可以防止任何进一步的 修改命名空间,允许新的活动节点安全地进行故障转移。
HA 架构总结如下:
1 、只有一个 NameNode Active 的,并且只有这个 Active NameNode 能提供服务,该 Active NameNode 宕机不可用的话,可以考虑让 Standby NameNode 切换成 Active 来提供服务。
2 、提供手动 Failover ,在升级过程中, Failover NameNode-DataNode 之间写不变的情况下才能生效。
3 、在之前的 NameNode 重新恢复之后,不能提供 failback
4 、数据一致性比 Failover 更重要。
5 、尽量少用特殊的硬件。
6 HA 的设置和 Failover 都应该保证在两者操作错误或者配置错误的时候,不得导致数据损坏。
7 NameNode 的短期垃圾回收不应该触发 Failover
8 DataNode 会同时向 Active NameNode Standby NameNode 汇报块的信息。
9 Active NameNode Standby NameNode 通过 NFS 备份 MetaData 信息到一个磁盘上面。

3.5、HDFS联邦集群

        单 NN 的架构使得 HDFS 在集群扩展性和性能上都有潜在的问题,当集群大到一定程度后, NN 进程使用的内存可能会达到上百G ,常用的估算公式为 1G 对应 1 百万个数据块,按缺省块大小计算的话,大概是 64T ( 这个估算比例是有比较大的富裕的,其实,即使是每个文件只有一个块,所有元数据信息也不会有 1KB/block) 。同时,所有的元数据信息的读取和操作都需要与 NN 进行通信,譬如客户端的addBlock、 getBlockLocations ,还有 DataNode blockRecieved、 sendHeartbeat blockReport , 在集群规模变大后,NN 成为了性能的瓶颈。 Hadoop 2.0 里的 HDFS Federation 就是为了解决这两个问题而开发的。

3.5.1、单个NamenodeHDFS架构的局限性

1. Namespace (命名空间)的限制
        由于 Namenode 在内存中存储所有的元数据( metadata ),因此单个 Namenode 所能存储的对象(文件+ 块)数目受到 Namenode 所在 JVM heap size 的限制。 50G heap 能够存储 20 亿( 200 million)个对象,这 20 亿个对象支持 4000 datanode 12PB 的存储(假设文件平均大小为40MB)。 随着数据的飞速增长,存储的需求也随之增长。单个 datanode 4T 增长到 36T ,集群的尺寸增长到8000 datanode 。存储的需求从 12PB 增长到大于 100PB
2. 性能的瓶颈
        由于是单个 NameNode HDFS 架构,因此整个 HDFS 文件系统的吞吐量受限于单个 Namenode 的吞吐量。毫无疑问,这将成为下一代 MapReduce 的瓶颈。
3. 隔离问题
        由于 HDFS 仅有一个 NameNode ,无法隔离各个程序,因此 HDFS 上的一个实验程序就很有可 能影响整个HDFS 上运行的程序。那么在 HDFS Federation 中,可以用不同的 Namespace 来 隔离不同的用户应用程序,使得不同Namespace Volume 中的程序相互不影响。
4. 集群的可用性
        在只有一个Namenode HDFS 中,此 Namenode 的宕机无疑会导致整个集群不可用。
5. Namespace Block Management 的紧密耦合
        当前在Namenode 中的 Namespace Block Management 组合的紧密耦合关系会导致如果想要实现另外一套Namenode 方案比较困难,而且也限制了其他想要直接使用块存储的应用。
6. 为什么纵向扩展目前的 Namenode 不可行?
        比如将 Namenode Heap 空间扩大到 512GB 。这样纵向扩展带来的第一个问题就是启动问题,启动花费的时间太长。当前具有 50GB Heap NameNode HDFS 启动一次大概需要 30 分钟到 2 小时,那512GB 的需要多久? 第二个潜在的问题就是 Namenode Full GC 时,如果发生错误将会导致整个集群宕机。 第三个问题是对大 JVM Heap 进行调试比较困难。优化 Namenode 的内存使用性价比比较低。

3.5.2、为什么要引入Federation

        引入 Federation 的最主要原因是简单,其简单性是与真正的分布式 Namenode 相比而言的。
Federation 能够快速的解决了大部分单 Namenode HDFS 的问题。
        Federation 是简单鲁棒的设计,由于联盟中各个 Namenode 之间是相互独立的。 Federation 整个核心设计实现大概用了3.5 个月。大部分改变是在 Datanode Confifig Tools ,而 Namenode 本身的改动非常少,这样Namenode 原先的鲁棒性不会受到影响。比分布式的 Namenode 简单,虽然这种实现的扩展性比起真正的分布式的 Namenode 要小些,但是可以迅速满足需求。另外一个原因是 Federation 良好的向后兼容性,已有的单 Namenode 的部署 配置不需要任何改变就可以继续工作。
        因此 Federation 是未来可选的方案之一。在 Federation 架构中可以无缝的支持目前 Namenode 架构中的配置。

3.5.3、HDFSFederation机制

        HDFS Federation 使用了多个独立的 NameNode/namespace 来使得 HDFS 的命名服务能够水平扩展。在 HDFS Federation 中的 NameNode 之间是联盟关系,他们之间相互独立且不需要相互协调。
        HDFS Federation 中的 NameNode 提供了提供了命名空间和块管理功能。 HDFS Federation 中的datanode 被所有的 NameNode 用作公共存储块的地方。每一个 datanode 都会向所在集群中所有的Namenode 注册,并且会周期性的发送心跳和块信息报告,同时处理来自 Namenode 的指令。

3.5.4、Federation HDFS与当前HDFS的比较及改进

        当前 HDFS 只有一个命名空间( NameSpace ),它使用全部的块。而 Federation HDFS 中有多个独立的命名空间(Namespace ),并且每一个命名空间使用一个块池( block pool )。当前 HDFS 中只有一组块。而 Federation HDFS 中有多组独立的块。块池( block pool )就是属于同一个命名空间的一组块。当前 HDFS 由一个 NameNode 和一组 datanode 组成。而 Federation HDFS 由多个Namenode 和一组 datanode ,每一个 datanode 会为多个块池( block pool )存储块。
1. Block Pool( 块池 )
        所谓 Block pool( 块池 ) 就是属于单个命名空间的一组 block( ) 。每一个 datanode 为所有的 block pool存储块。 Datanode 是一个物理概念,而 block pool 是一个重新将 block 划分的逻辑概念。同一个 datanode中可以存着属于多个 block pool 的多个块。 Block pool 允许一个命名空间在不通知其他命名空间的情况下为一个新的 block 创建 Block ID 。同时,一个 Namenode 失效不会影响其下的 datanode为其他Namenode 的服务。 当 datanode Namenode 建立联系并开始会话后自动建立 Block pool 。每个block 都有一个唯一的标识, 这个标识我们称之为扩展的块 ID Extended Block ID =BlockID+BlockID。这个扩展的块 ID HDFS 集群之间都是唯一的,这为以后集群归并创造了条件。Datanode中的数据结构都通过块池 ID BlockPoolID )索引,即 datanode 中的 BlockMap storage 等都通过BPID 索引。
        在HDFS中,所有的更新、回滚都是以 Namenode BlockPool 为单元发生的。即同一 HDFS Federation中不同的Namenode/BlockPool 之间没有什么关系。 Hadoop V0.23 版本中 Block Pool 的管理功能依然放在了Namenode 中,将来的版本中会将 Block Pool 的管理功能移动的新的功能节点中。
2. Datanode 的改进
        在datanode 中,对应于每个 Namnode 都有一条相应的线程。每个 datanode 会去每一个 Namenode 注册,并且周期性的给所有的Namenode 发送心跳及 datanode 的使用报告。 Datanode 还会给
Namenode 发送其所在的 block pool block report (块报告)。由于有多个 Namenode 同时存在,
因此任何一个 Namenode 都可以随时动态加入、删除和更新。
3. Federation 中的其他方面的改进
        提供了工具,对于Namenode 的初始化和退役的监控和管理。 允许在 datanode 级别或者 block pool 级 别的负载均衡。 Datanode 的后台守护进程,为 Federation 所做的磁盘和目录扫描。 提供了显示
Namenode Block pool 的使用状态的 Web UI 。 还提供了对全部集群存储使用状态的 UI 展示。 在 Web UI中列出了所有的 Namenode 及其细节,如 Namenode-BlockPoolID 和存储的使用状态,失去联系的、 活的和死的块信息。还有前往各个Namenode Web UI 的链接。 Datanode 退役状态的展示。
4. 多命名空间的管理问题
        在一个集群中需要唯一的命名空间还是多个命名空间,核心问题命名空间中数据的共享和访问的问题。使用全局唯一的命名空间是解决数据共享和访问的一种方法。在多命名空间下, 我们还可以使用Client Side Mount Table方式做到数据共享和访问。
5. Namespace Volume (命名空间卷)
        一个 Namespace 和它的 Block Pool 合在一起称作 Namespace Volume Namespace Volume 是一 个独立完整的管理单元。当一个 Namenode/Namespace 被删除,与之相对应的 BlockPool 也被删除。在升级时每一个Namespace Volume 也会整体作为一个单元。
6. ClusterID
        在 HDFS Federation 中添加了 Cluster ID 用来区分集群中的每个节点。当格式化一个 Namenode
时,这个 ClusterID 会自动生成或者手动提供。在格式化同一集群中其他 Namenode 时会用到这个
ClusterID
7. HDFS Federation 对老版本的 HDFS 是兼容的
        这种兼容性可以使得已有的 Namenode 配置不需要任何改变继续工作。
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值