Hadoop1.0存在的问题
- NameNode SPOF,NameNode挂掉整个集群不可用
- 内存受限,整个集群的size受限于NameNode的内存空间大小
HDFS2.0的解决方案
HDFS2.0的HA概览
1.两个名称节点:
Standy NN在承担了Secondary NN的职责之外,还作为A NN的热备,防止单点故障问题。
Active NameNode 主
Standby NameNode 热备
2.共享存储系统:实现名称节点的状态同步
3.ZooKeeper:会进行心跳检查,确保一个名称节点在对外服务
4.名称节点:维护映射信息
5.数据节点:同时向两个名称节点汇报信息
6.优点:热备份,提供高可用性
7.不足:无法解决可扩展性、系统性能和隔离性
HA的设计解决了什么问题?
1.主备一致实现
如何保证主备NN之间的同步是HA正常工作的关键。
- Active NameNode启动后提供服务,并把Editlog写到本地和QJM中。
- Standby NameNode会周期性的从QJM中拉取Editlog,保持与active的状态同步。
- 双写:DataNode同时两个NameNode发送BlockReport,但是只有Active NN可以响应DD。
2.脑裂的解决
脑裂问题就是产生了两个leader,导致集群行为不一致了,而我们为了保证数据的一致性,只能有一个Active NN。
- 仲裁:当两个节点出现分歧时,由第3方的仲裁者决定听谁的。
- fencing:当不能确定某个节点的状态时,通过fencing把对方干掉,确保共享资源被完全释放。
三个组件中的fencing
QJM的fencing,确保只有一个NN能写成功。
QJM也是一个多节点集群,负责EditLog的写入和更新,所以要保证只有一个Active NN能写入成功,是依赖自增的选举轮数来保证的,类似kafka的controller在zk中的选举。
1. 高可用
QJM全称是Quorum Journal Manager, 由JournalNode(JN)组成,一般是奇数个结点组成。当存活
的节点数为偶数个时,无法提供正常服务。
2. 基于Paxos
NameNode会同时向所有JournalNode并行写文件,只要有N/2+1个结点写成功则认为此次写操作成功,遵循Paxos协议。
3. 防止双写
Epoch Numbers即选举轮数,NN把自己的Epoch Number通过发送给所有JN结点,NN同步日志到JN的任何RPC请求都必须包含这个Epoch Number。
JN会对比每次请求中的Epoch Number和保存在本地的Epoch Number,只对Epoch Number更大的请求进行处理,更新本地保存的Epoch Number
DataNode的fencing,确保只有一个NN能命令DN
DataNode则是根据NN的序列号大小来保证只有一个NN的指令能成功。
1. 每个NN改变状态的时候,向DN发送自己的状态和一个序列号(类似Epoch Numbers)。
2. DN在运行过程中维护此序列号,当failover时,新的NN在返回DN心跳时会返回自己的active状态和一个更大的序列号。DN接收到这个返回则认为该NN为新的active。
3. 如果这时原来的active NN恢复,返回给DN的心跳信息包含active状态和原来的序列号,这时DN就会拒绝这个NN的命令。
客户端fencing,确保只有一个NN能响应客户端请求。
客户端的fencing比较简单,选举过程会有一段恢复时间,client会在两种NN中反复横跳,直到选举出Active NN,或者达到最大重试次数45次返回错误。
让访问Standby NN的客户端直接失败:
1. 在RPC层封装了一层,通过FailoverProxyProvider以重试的方式连接NN。
2. 通过若干次连接一个NN失败后尝试连接新的NN,对客户端的影响是重试的时候增加一定的延迟。
3. 客户端可以设置重试次数和时间。
3.透明切换(failover)
NameNode切换对外透明,主Namenode切换到另外一台机器时,不应该导致正在连接的客户端失败,主要包括Client、Datanode与NameNode的链接。
主备切换的实现:ZKFC
ZKFC即ZKFailoverController,作为独立进程存在,负责控制NameNode的主备切换,ZKFC会监测NameNode的健康状况,当发现Active NameNode出现异常时会通过ZooKeeper集群进行一次主备选举,完成Active和Standby状态的切换。ZKFC优点类似Redis中的哨兵。
ZKFC实现下述几个功能
- 监控NameNode的健康状态。
- 向ZK定期发送心跳,使自己可以被选举。
- 当自己被ZK选为主时,active ZKFC使相应的NN转换为active。
HDFS1.0 命名空间结构
Namespace:
由目录、文件和数据块组成,支持常见的文件系统操作,例如创建、删除、修改和列出文件和目录。
Block Storage Service:
1.数据块管理
这个模块由NameNode提供,分为数据块管理和存储
Ø 通过处理DataNode的注册和定期心跳来提供集群中DataNode的基本关系;
Ø 维护数据到数据块的映射关系,以及数据块在DataNode的映射关系;
Ø 支持数据块相关操作,如创建、删除、修改和获取块位置;
Ø 管理副本的放置、副本的创建,以及删除多余的副本。
2.存储( Storage) - 是由DataNode提供,主要在本地文件系统存储数据块,并提供读写访问
HDFS Federation
设计特点
• NameNode共享底层的数据节点存储资源
• DataNode向所有NameNode汇报
• 属于同一个Namespace的块构成一个block pool
• 可以存在多个相互独立的NameNode
• 水平扩展的命名服务
• 独立管理Namespace和block pool
• 联邦(Federation)关系不需要彼此协调
• 向后兼容
4个设计原则
- 一个Namespace对应一个Block Pool
- 一个Block Pool是属于某个namespace下的一系列block。
- DataNode是共享的,不同Block Pool的block在同一个DataNode上存储。
- 一个Namespace和它的block pool一起被叫做Namespace Volume。
总结
NN彼此之间独立,所有NN共享DN,NN和BP一一对应,BP包含一个NN下的所有B。
存在的三个问题
- 客户端都要更新配置文件,并维护多个Namespace
- 访问目录需要指定完整路径
- 当Namespace增多以后,管理和访问非常不方便
ViewFs
ViewFs(视图文件系统)可以解决上述的第二个问题,其基于客户端。
ViewFs简单的可以理解为这是一个虚拟的,逻辑上的文件系统。因为这个文件系统实际并不真实存在,只是我们构建了这个文件系统,它的底层指向了实际意义上的多物理集群。ViewFs实际上是使用挂载表(Mount Table)做到的。
ViewFS存在的问题和3.0的解决
ViewFS方案也存在一些问题:
• 对于已经发不出去的客户端,升级比较困难;
• 对于新增目录,需要添加挂在表与产品对接,维护起来比较困难。
HD社区在2.9和3.0发布了一个新的解决统一命名空间的方案RBF:Router-Based Federation (HDFS-10467)该方案是基于服务端实现的,大大简化了升级和管理方面的难度,这个会在后面的文章介绍