1.1 Hadoop1.x带来的问题
1、单点故障
a. 每个群集只有一个NameNode,NameNode存在单点故障(SPOF)。 b. 如果该计算机或进程不可用,则整个群集在整个NameNode重新启动或在另一台计算机上启 动之前将不可用 c. 如果发生意外事件(例如机器崩溃),则在操作员重新启动NameNode之前,群集将不可 用。 d. 计划内的维护事件,例如NameNode计算机上的软件或硬件升级,将导致群集停机时间的延 长 2、水平扩展 将来服务器启动的时候,启动速度慢
3、namenode随着业务的增多,内存占用也会越来越多 如果namenode内存占满,将无法继续提供服务
4、日志丢失问题
1.2 设计思路
1、hadoop2.x启用了主备节点切换的模式(1主1备)
2、当主节点出现异常的时候,集群直接将备用节点切换成主节点
要求备用节点马上就要工作
主备节点内存几乎同步 有
3、独立的线程对主备节点进行监控健康状态
4、需要有一定的选举机制,帮助我们确定主从关系
5、我们需要实时存储日志的中间件
1.3 组织架构
Active NameNode(ANN)
a. 它的功能和原理的NN的功能是一样的
b. 接受客户端请求,查询数据块DN信息
c. 存储数据的元数据信息
数据文件:Block:DN的映射关系
d. 工作
启动时:接受DN的block汇报
运行时:和DN保持心跳(3s,10m)
e. 存储介质
完全基于内存
优点:数据处理效率高
缺点:数据的持久化(日志edits+快照fsimage)
Standby NameNode(SNN)
a. Standby NameNode:NN的备用节点
b. 他和主节点做同样的工作,但是它不会发出任何指令
c. 存储:数据的元数据信息
数据文件:Block:DN的映射关系 它的内存数据和主节点内存数据几乎是一致的
d. 工作:
启动时: 接受DN的block汇报 运行时: 和DN保持心跳(3s,10m)
e. 存储介质:完全基于内存
优点:数据处理效率高
缺点:数据的持久化
# f. 合并日志文件和镜像
1)当搭建好集群的时候,格式化主备节点的时候,ANN和SNN都会默认创建 fsimage_000000000000000这样的镜像文件
2)当我们操作HDFS的时候ANN会产生日志信息edits_inprogress_0000000000001
3)主节点会将日志文件中新增的数据同步到JournalNode集群上
4)所以只需要snn有操作的日志信息,就可以合并fsImage与edits信息,理论上是一直在合并数据
fsimage -->初始化创建
edits-->从JournalNode集群上定时同步
现在只要同步到edits文件,就开始于fsimage合并
当达到阈值的时候,直接拍摄快照即可
5) SNN将合并好的Fsimage发送给ANN,ANN验证无误后,存放到自己的目录中
DataNode(DN)
a. 存储文件的Block数据
b. 介质:硬盘
c. 启动时:同时向两个NN汇报Block信息
d. 运行中:同时和两个主节点保持心跳机制
JournalNode(JN)
a. Quorum JournalNode Manager 共享存储系统,NameNode通过共享存储系统实现日志数据同 步。
b. JournalNode是一个独立的小集群,它的实现原理和Zookeeper的一致( Paxos)
c. ANN产生日志文件的时候,就会同时发送到 JournalNode的集群中每个节点上
d. JournalNode不要求所有的jn节点都接收到日志,只要有半数以上的(n/2+1)节点接受收到日 志,那么本条日志就生效
e. SNN每间隔一段时间就去QJM上面取回最新的日志
SNN上的日志有可能不是最新的
f. HA集群的状态正确至关重要,一次只能有一个NameNode处于活动状态。
g. JournalNode只允许单个NameNode成为活跃的主节点。在故障转移期间,将变为活动状态的NameNode 将承担写入JournalNodes的角色,这将有效地防止另一个NameNode继续处于活动状态,从而使 新的Active节点可以安全地进行故障转移。
Failover Controller(ZKFC:故障转移控制器)
# 对 NameNode 的主备切换进行总体控制,能及时检测到 NameNode 的健康状况,在主 NameNode 故障时借助 Zookeeper 实现自动的主备选举和切换,为了防止因为NN的GC失败导致心跳受影响,ZKFC作为一个deamon进程从NN分离出来
1) 启动时:
当集群启动时,主备节点的概念是很模糊的 当ZKFC只检查到一个节点是健康状态,直接将其设置为主节点 当zkfc检查到两个NN节点是的健康状态,发起投票机制 选出一个主节点,一个备用节点,并修改主备节点的状态
一个常见的问题:如果启动的时候,发现有两个备用节点,肯定是因为没有选举,检查一下zookeeper有没有启动起来,如果还是失败,重启一下
问题:
1、SNN为什么不直接去ANN去同步数据。
2、SNN挂了谁去合并日志呢?没有人
2) 运行时:
由 ZKFailoverController、HealthMonitor 和 ActiveStandbyElector 这 3 个组件来协同实现主备切换
a. ZKFailoverController启动的时候会创建 HealthMonitor 和 ActiveStandbyElector 这两 个主要的内部组件 b. HealthMonitor 主要负责检测 NameNode 的健康状态
c. ActiveStandbyElector 主要负责完成自动的主备选举,内部封装了 Zookeeper 的处理逻辑
3) 主备节点正常切换 NameNode 在选举成功后, ActiveStandbyElector 会在 zk 上创建一个 ActiveStandbyElectorLock 临时节点,而没有选举成功的备 NameNode 中的ActiveStandbyElector 会监控这个节点
如果 Active NameNode 对应的 HealthMonitor 检测到 NameNode 的状态异常时,ZKFailoverController 会主动删除当前在 Zookeeper 上建立的临时节点ActiveStandbyElectorLock
处于 Standby 状态的 NameNode 的 ActiveStandbyElector 注册的监听器就会收到这个节点的 NodeDeleted 事件,并创建 ActiveStandbyElectorLock 临时节点,本来处于 Standby 状态的 NameNode 就选举为 Active NameNode 并随后开始切换为 Active 状态。
如果是 Active NameNode 的机器整个宕掉的话,那么跟 zookeeper 连接的客户端线程也挂了 , 会话结束 , 那么根据 Zookeepe 的临时节点特性, ActiveStandbyElectorLock 节点会自动被删除,从而也会自动进行一次主备切换,
Zookeeper 为主备切换控制器提供主备选举支持。 辅助投票 和 ZKFC 保持心跳机制,确定 ZKFC 的存活
1.4 脑裂brain-split
定义 脑裂是 Hadoop2.X 版本后出现的全新问题,实际运行过程中很有可能出现两个 namenode 同时服务于整个集群的情况,这种情况称之为脑裂。
原因 脑裂通常发生在主从 namenode 切换时,由于 ActiveNameNode 的网络延迟、设备故障等问题,另一个 NameNode 会认为活跃的 NameNode 成为失效状态,此时 StandbyNameNode 会转换成活跃状态,此时集群中将会出现两个活跃的 namenode 。因此,可能出现的因素有网络延迟、心跳故障、设备故障等。
脑裂场景 NameNode 可能会出现这种情况, NameNode 在垃圾回收( GC )时,可能会在长时间内整个系统无响应 zkfc 客户端也就无法向 zk 写入心跳信息,这样的话可能会导致临时节点掉线,备 NameNode会切换到 Active 状态 这种情况可能会导致整个集群会有同时有两个 Active NameNode
脑裂问题的解决方案是隔离( Fencing )
第三方共享存储:任一时刻,只有一个 NN 可以写入;
DataNode :需要保证只有一个 NN 发出与管理数据副本有关的命令;
Client 需要保证同一时刻只有一个 NN 能够对 Client 的请求发出正确的响应。 a) 每个 NN 改变状态的时候,向 DN 发送自己的状态和一个本次选举对应的序列号。 b) DN 在运行过程中维护此序列号,当 failover 时,新的 NN 在返回 DN 心跳时会返回自己的 active 状态和一个更大的序列号。 DN 接收到这个返回是认为该 NN 为新的 active 。 (c) 如果这时原来的 active (比如 GC )恢复,返回给 DN 的心跳信息包含 active 状态和原来的序列号,这时 DN 就会拒绝这个 NN 的命令。 解决方案 ActiveStandbyElector 为了实现 fencing ,当 NN 成为 ANN 之后创建 Zookeeper 临时节点ActiveStandbyElectorLock ,创建 ActiveBreadCrumb 的持久节点,这个节点里面保存了这个Active NameNode 的地址信息 (node-01) Active NameNode 的 ActiveStandbyElector 在正常的状态下关闭 Zookeeper Session 的时候,会一起删除这个持久节点 但如果 ActiveStandbyElector 在异常的状态下关闭,那么由于 /hadoop ha/${dfs.nameservices}/ActiveBreadCrumb 是持久节点,会一直保留下来,后面当另一个NameNode 选主成功之后,会注意到上一个 Active NameNode 遗留下来的这个节点,从而会回调 ZKFailoverController 的方法对旧的 Active NameNode 进行 fencing 。 首先尝试调用这个旧 Active NameNode 的 HAServiceProtocol RPC 接口的transitionToStandby 方法,看能不能把它转换为 Standby 状态; 如果 transitionToStandby 方法调用失败,那么就执行 Hadoop 配置文件之中预定义的隔离措施。
sshfence :通过 SSH 登录到目标机器上,执行命令 fuser 将对应的进程杀死
shellfence :执行一个用户自定义的 shell 脚本来将对应的进程隔离 在成功地执行完成 fencing 之后,选主节点成功的 ActiveStandbyElector 才会回调ZKFailoverController 的 becomeActive 方法将对应的 NameNode 转换为 Active 状态,开始对外提供服务。新的主创建临时节点 ActiveStandbyElectorLock ,创建持久化节点 ActiveBreadCrumb ,并将自己的主机地址 Node02 赋值给初始化节点
二、Hadoop-federation
HDFS federation就是使得HDFS支持多个命名空间,并且允许在HDFS中同时存在多个Name Node
2.1 单NN局限性
Namespace(命名空间)的限制
单个datanode从4T增长到36T,集群的尺寸增长到8000个datanode。存储的需求从12PB增长到大于100PB。
性能的瓶颈
由于是单个Namenode的HDFS架构,因此整个HDFS文件系统的吞吐量受限于单个Namenode的吞吐量。毫无疑问,这将成为下一代MapReduce的瓶颈。
隔离问题
由于HDFS仅有一个Namenode,无法隔离各个程序,因此HDFS上的一个实验程序就很有可能影响整个HDFS上运行的程序。那么在HDFS Federation中,可以用不同的Namespace来隔离不同的用户应用程序,使得不同Namespace Volume中的程序相互不影响。
集群的可用性
在只有一个Namenode的HDFS中,此Namenode的宕机无疑会导致整个集群不可用。
Namespace和Block Management的紧密耦合
当前在Namenode中的Namespace和Block Management组合的紧密耦合关系会导致如果想要实现另外一套Namenode方案比较困难,而且也限制了其他想要直接使用块存储的应用。
为什么纵向扩展目前的Namenode不可行?比如将Namenode的 JVM Heap空间扩大到512GB。
这样纵向扩展带来的第一个问题就是启动问题,启动花费的时间太长。当前具有50GB Heap Namenode的HDFS启动一次大概需要30分钟到2小时,那512GB的需要多久?第二个潜在的问题就是Namenode在Full GC时,如果发生错误将会导致整个集群宕机。第三个问题是对大JVM Heap进行调试比较困难。优化Namenode的内存使用性价比比较低。
2.2 federation
画图带大家理解
NameNode提供了命名空间(NameSpace)和块(Block)管理功能。 HDFS 联邦拥有多个独立的命名空间,每个空间管理属于自己的一组块,这些同组的块构成了“块 池”(Block Pool)。 所有的NameNode 会共享底层的数据节点的存储资源。数据节点是一个物理概念,块池则属于逻辑概念。
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版本中Block Pool的管理功能依然放在了Namenode中,将来的版本中会将Block Pool的管理功能移动的新的功能节点中。
Namespace Volume(命名空间卷)
一个Namespace和它的块池合并在一起称为Namespace Volume,它是一个独立完整的管理单元。
当一个Namenode/Namespace被删除,与之相对应的块池也被删除。
在升级时,每一个nanespace Volume也会整体作为一个单元。
通过多个namenode/namespace把元数据的存储和管理分散到多个节点中
降低单个节点数据压力,计算压力
namenode/namespace可以通过增加机器来进行水平扩展
可以让更多的节点参与到运算
namespace命名空间,通过这种方式确定要处理数据的路径
我们可以通过namenode和namespace组合使用
所有的nn共享dn
但是每一个namespace会单独管理自己的模块
会创建一个管理块的机制:blocks pool
注意:联邦机制和HA完全不一样的,是解决不一样的问题,联邦机制解决的是业务水平扩展的问题,HA解决的是单点故障的问题