Hadoop-第四周

一、熟悉HDFS  HA实现机制

1.1 整体架构

一个典型的HA集群,NameNode会被配置在两台独立的机器上,在任何时间上,一个NameNode处于活动状态,而另一个NameNode处于备份状态,活动状态的NameNode会响应集群中所有的客户端,备份状态的NameNode只是作为一个副本,保证在必要的时候提供一个快速的转移。

为了让Standby Node与Active Node保持同步,这两个Node都与一组称为JNS的互相独立的进程保持通信(Journal Nodes)。当Active Node上更新了namespace,它将记录修改日志发送给JNS的多数派。Standby noes将会从JNS中读取这些edits,并持续关注它们对日志的变更。Standby Node将日志变更应用在自己的namespace中,当failover发生时,Standby将会在提升自己为Active之前,确保能够从JNS中读取所有的edits,即在failover发生之前Standy持有的namespace应该与Active保持完全同步。

为了支持快速failover,Standby node持有集群中blocks的最新位置是非常必要的。为了达到这一目的,DataNodes上需要同时配置这两个Namenode的地址,同时和它们都建立心跳链接,并把block位置发送给它们。

任何时刻,只有一个Active NameNode是非常重要的,否则将会导致集群操作的混乱,那么两个NameNode将会分别有两种不同的数据状态,可能会导致数据丢失,或者状态异常,这种情况通常称为“split-brain”(脑裂,三节点通讯阻断,即集群中不同的Datanodes却看到了两个Active NameNodes)。对于JNS而言,任何时候只允许一个NameNode作为writer;在failover期间,原来的Standby Node将会接管Active的所有职能,并负责向JNS写入日志记录,这就阻止了其他NameNode基于处于Active状态的问题。

 

首先要部署三台zk,然后要两台NN节点,然后三台DN节点。两个NN节点之间的编辑日志需要jn来维护,做共享数据存储。

journalnode(jn): 部署多少合适?取决于HDFS请求量及数据量,比如说BT级的数据量,或者小文件很多,读写请求很频繁,那么journalnode就部署多一点,如果HDFS很悠闲,那就部署少一点,比如7个、9个这样,可以大致和zk部署的保持一致(见上面)。具体要看实际情况。(也是2n+1,可以看官网上介绍)

每个DataNode节点要向两个NameNode都发送心跳报告。(面试,为什么)

在这里ZKFC是进程,(但是在yarn ha 里,zkfc是线程)

进程:ps -ef 看到的就是进程,是由1个以上的线程组成。

线程:线程是进程的一部分

ZKFC:zookeeperfailovercontrol

客户端或者程序代码在提交的时候,去namespace找,找NN节点,如果第一次找的NN节点就是active,那么就用这个节点,如果发现它是standby,就到另外一台机器。

比如说客户端现在执行put、get、ls、cat命令,这些操作命令的记录,active NN节点会写到自己的edit log日志里面。这些操作记录,NN自己会写一份,同时,它会把这些操作记录,写给journalnode的node集群。

而另外的,standby NN节点,会实时的读journalnode的node集群,读了之后会把这些记录应用到自己的本身。这个大数据的专业名词叫做:重演。 相当于standby NN节点把active NN节点的active状态的操作记录在自己身上重演一遍。

journalnode:它是一个集群,就是用于active NN节点和standby NN节点之间同步数据的。它是单独的进程。

NN和ZKFC在同一台机器上面。

整个过程描述:当通过client端提交请求的时候,无论读和写,我们是通过命名空间RUOZEG6,去找谁是active状态,找到了就在那台机器上面,提交请求,然后就是HDFS的读写流程,读和写的操作记录,edit log,它自己会写一份,同时会把读写请求的操作记录,写一份到journalnode集群日志,进行同步之后,另外一个节点,standby 节点会把它拿过来实时的应用到自己的本身。专业的名称叫重演。同时每个DataNode会向NameNode节点发送心跳的块报告(心跳的间隔时间3600s,就是1小时,参数是什么(面试))。当active NN节点挂了,通过zk集群选举(它存储了NN节点的状态),通知ZKFC,把standby NN节点切换到active状态。ZKFC会定期的发送心跳。

ps:

HA是为了解决单点故障问题。

通过journalnode集群共享状态,也就是共享hdfs读和写的操作记录。

通过ZKFC集群选举谁是active。

监控状态,自动备援。

DN: 同时向NN1 NN2发送心跳和块报告。
ACTIVE NN: 读写的操作记录写到自己的editlog
                     同时写一份到JN集群
                     接收DN的心跳和块报告
STANDBY NN: 同时接收JN集群的日志,显示读取执行log操作(重演),使得自己的元数据和active nn节点保持一致。
                        接收DN的心跳和块报告

JounalNode: 用于active nn和 standby nn节点的数据同步, 一般部署2n+1

ZKFC: 单独的进程
           监控NN监控健康状态
           向zk集群定期发送心跳,使得自己可以被选举;
           当自己被zk选举为active的时候,zkfc进程通过RPC协议调用使NN节点的状态变为active,只有是
active状态才能对外提供服务。
           对外提供实时服务,是无感知的,用户是感觉不到的。
 

HDFS&YARN HA架构剖析

Hadoop HA架构简述

HDFS HA与联邦原理

 

1.2 QJM 元数据共享机制

1.2.1 QJM介绍

QJM全称是Quorum Journal Manager, 由JournalNode(JN)组成,一般是奇数点结点组成。每个JournalNode对外有一个简易的RPC接口,以供NameNode读写EditLog到JN本地磁盘。当写EditLog时,NameNode会同时向所有JournalNode并行写文件,只要有N/2+1结点写成功则认为此次写操作成功,遵循Paxos协议。其内部实现框架如下:

从图中可看出,主要是涉及EditLog的不同管理对象和输出流对象,每种对象发挥着各自不同作用:

  • FSEditLog:所有EditLog操作的入口
  • JournalSet: 集成本地磁盘和JournalNode集群上EditLog的相关操作
  • FileJournalManager: 实现本地磁盘上 EditLog 操作
  • QuorumJournalManager: 实现JournalNode 集群EditLog操作
  • AsyncLoggerSet: 实现JournalNode 集群 EditLog 的写操作集合
  • AsyncLogger:发起RPC请求到JN,执行具体的日志同步功能
  • JournalNodeRpcServer:运行在 JournalNode 节点进程中的 RPC 服务,接收 NameNode 端的 AsyncLogger 的 RPC 请求。
  • JournalNodeHttpServer:运行在 JournalNode 节点进程中的 Http 服务,用于接收处于 Standby 状态的 NameNode 和其它 JournalNode 的同步 EditLog 文件流的请求。

Hadoop-QJM原理

HDFS之Qurom Journal Manager(QJM)实现机制分析

HDFS QJM机制分析

 

1.3 主备选举和自动切换的实现

HDFS的集群HA的主备自动切换搭建

 

1.4 防“脑裂”机制

1.4.1 什么是脑裂

脑裂是Hadoop2.X版本后出现的全新问题,从字面意思我们可以理解为“大脑分裂”;

我们想一下,当一个正常人,突然出现有了两个大脑,而且这两个大脑都有自己的意识,对于这个人来说肯定是灾难性问题。

同理,在Hadoop中,为了防止单点失效问题而出现了两个namenode(HA机制),这两个namenode正常情况下是起到一个失效,

另一个代替的作用,但在实际运行过程中很有可能出现两个namenode同时服务于整个集群的情况,这种情况称之为脑裂。

1.4.2 为什么会出现脑裂

脑裂通常发生在主从namenode切换时,由于ActiveNameNode的网络延迟、设备故障等问题,另一个NameNode会认为活跃的NameNode成为失效状态,

此时StandbyNameNode会转换成活跃状态,此时集群中将会出现两个活跃的namenode。因此,可能出现的因素有网络延迟、心跳故障、、设备故障等。

1.4.3 怎么解决脑裂问题

脑裂问题的解决方案是隔离(Fencing),主要是在以下三处采用隔离措施:

(1)第三方共享存储:任一时刻,只有一个 NN 可以写入;

(2)DataNode:需要保证只有一个 NN 发出与管理数据副本有关的删除命令;

(3)Client:需要保证同一时刻只有一个 NN 能够对 Client 的请求发出正确的响应。

关于这个问题目前解决方案的实现如下:

(1)ActiveStandbyElector 为了实现 fencing,会在成功创建 Zookeeper 节点 hadoop-ha/${dfs.nameservices}/ActiveStandbyElectorLock 从而成为 Active NameNode 之后,创建另外一个路径为 /hadoop-ha/${dfs.nameservices}/ActiveBreadCrumb 的持久节点,这个节点里面保存了这个 Active NameNode 的地址信息;

(2)Active NameNode 的 ActiveStandbyElector 在正常的状态下关闭 Zookeeper Session 的时候,会一起删除这个持久节点;

(3)但如果 ActiveStandbyElector 在异常的状态下 Zookeeper Session 关闭 (比如前述的 Zookeeper 假死),那么由于 /hadoop-ha/${dfs.nameservices}/ActiveBreadCrumb 是持久节点,会一直保留下来,后面当另一个 NameNode 选主成功之后,会注意到上一个 Active NameNode 遗留下来的这个节点,从而会回调 ZKFailoverController 的方法对旧的 Active NameNode 进行 fencing。

在进行 fencing 的时候,会执行以下的操作:

  1. 首先尝试调用这个旧 Active NameNode 的 HAServiceProtocol RPC 接口的 transitionToStandby 方法,看能不能把它转换为 Standby 状态;
  2. 如果 transitionToStandby 方法调用失败,那么就执行 Hadoop 配置文件之中预定义的隔离措施。

Hadoop 目前主要提供两种隔离措施,通常会选择第一种:

  1. sshfence:通过 SSH 登录到目标机器上,执行命令 fuser 将对应的进程杀死;
  2. shellfence:执行一个用户自定义的 shell 脚本来将对应的进程隔离。

只有在成功地执行完成 fencing 之后,选主成功的 ActiveStandbyElector 才会回调 ZKFailoverController 的 becomeActive 方法将对应的 NameNode 转换为 Active 状态,开始对外提供服务。

 

1.5 HA 相关配置和管理

Hadoop-HA配置

Hadoop HA

 

二、HDFS可靠性保障机制

2.1 租约恢复

2.1.1 背景  

在HDFS中可能同时有多个客户端在同一时刻写文件,如果不进行控制的话,有可能多个客户端会并发的写一个文件,所以需要进行控制,一般的想法是用一个互斥锁,在某一时刻只有一个客户端进行写操作,但是在分布式系统中有如下问题:

  1.每次写文件前,客户端需要向master获取锁情况,他们之间的网络通讯太频繁。

  2.当某个客户端获取锁之后和master失去联系,这个锁一直被该客户端占据,master和其他客户端不能获得锁,后续操作中断。

2.1.2 解决方案

在HDFS中使用了租约解决上面的问题

  1.当写一个文件时,客户端向NameNode请求一个租约,租约有个时间期限,在时间期限内客户端可以写租约中管理的文件,一个文件只可能在一个租约内,所以只可能有一个客户端写。

  2.在租约的有效时间内,客户端不需要向NameNode询问是否有写文件的权限,客户端会一直持有,当客户端一直正常的时候,客户端在租约过期的时候会续约。

  3.当客户端在持有租约期间如果发生异常,和NameNode失去联系,在租约期满以后NameNode会发现客户端异常,新的租约会赋给其他正常的客户 端,当异常客户端已经写了一部分数据,HDFS为了分辨这些无用的数据,每次写的时候会增加版本号,异常客户端写的数据版本号过低,可以安全的删除掉。

HDFS中的LeaseManager是租约管理器,主要管理着下面这三部分数据:

//
  // Used for handling lock-leases
  // Mapping: leaseHolder -> Lease
  //
  privateSortedMap<String, Lease> leases =newTreeMap<String, Lease>();
  // Set of: Lease
  privateSortedSet<Lease> sortedLeases =newTreeSet<Lease>();
 
  //
  // Map path names to leases. It is protected by the sortedLeases lock.
  // The map stores pathnames in lexicographical order.
  //
  privateSortedMap<String, Lease> sortedLeasesByPath =newTreeMap<String, Lease>();


第一部分保存的数据是客户端和Lease的映射

第二部分保存的数据是所有的lease集合,按照上次租约更新时间进行排序,上次租约更新时间离当前时间越长的越排在前面。

第三部分保存的数据是文件名和lease的映射,按照文件名的字典顺序进行排序

在LeaseManager中有个Monitor线程在不停的检查lease集合,检查是否有lease过期,如果lease过期,会将对应的lease删除。

在DFSClient中有一个LeaseChecker线程,该线程周期性的检查租约是否过期,在快过期的时候就会续约租约,这是个后台线程,当DFSClient挂了,这个线程也挂了,租约也不能续约了.

 

HDFS写入过程客户端奔溃怎么处理?(租约恢复)

2.2 块恢复

检测缺失块

hdfs fsck -list-corruptfileblocks

hdfs fsck / | egrep -v '^\.+$' | grep -v eplica

查看上面某一个文件的情况

hdfs fsck /path/to/corrupt/file -locations -blocks -files

解决方法

手动修复
hdfs fsck / #检查集群的健康状态
hdfs debug recoverLease -path 文件位置 -retries 重试次数 #修复指定的hdfs数据块。也就是关闭打开的文件。

检查坏块:
hadoop fsck /user -files -blocks -locations

检查是否有数据块正在写入:
hadoop fsck /user openforwrite

 

HDFS上块恢复机制

如何恢复hdfs中丢失的块

 

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值