大数据_hadoop_hdfs

架构

NameNode和DataNode

角色
NameNode为管理节点,执行对文件系统命名空间的操作,如:打开、关闭和重命名文件或目录;并且决定文件块与datanode之间的映射关系。
DataNode为工作节点,响应文件系统客户端的读写请求,存储并检索数据块。并定期向namenode发送它们存储的块的列表,接收来自NameNode的文件块创建、删除和复本改进等命令。

数据块
一个文件一般会被切分成多块存储在多个DataNode中。HDFS使用的典型块大小为64 MB。

命名空间

HDFS与传统的分级文件类似,可以创建目录,在目录下存储文件等操作,不能创建软链接、硬链接等操作。
NameNode维护着命名空间,任何改动都会记录在NameNode中。程序可以指定文件在hdfs中的备份数,备份数称为replication factor,该信息也存在NameNode中

数据备份

HDFS将一个文件切分成多个文件块(block)存储,除最后一块的所有文件块大小相同。
为了容错性每个文件块都有备份,每个文件块大小和备份数都可以配置。程序(Application)可以指定备份数,replication factor可以在文件创建的时候指定,也可在之后修改(hadoop dfs -setrep)。
文件一次写入HDFS中,且每个时刻只有一个writer。

NameNode决定决定的块复制。它定期从群集中的每个DataNode接收Heartbeat和Blockreport。收到Heartbeat意味着DataNode运行正常。Blockreport包含DataNode上所有块的列表。

  • 备份存放:这里拿复制因子为3的一般情况来说,HDFS的放置策略是将一个副本放在本地机架上的一个节点上,另一个放在本地机架上的不同节点上,最后放在另一个机架上的不同节点上。放置不同的机架更容易保证容错性。
  • 副本选择:选择距离reader最近的副本。如果在reader节点(node)相同机架上存在副本,那么就读相同机架上的副本。
  • 安全模式:当以下情况会出现安全模式:
    • 集群启动时,namenode会进入安全模式,当每个数据块最少副本数在namenode中被确认存在时,会自动退出安全模式。
    • 当namenode发现集群中的block丢失数量达到一个阀值时(0.01%)

在安全模式中,只允许查看数据不允许对数据进行任何操作。
集群升级维护时手动进入安全模式

hadoop dfsadmin -safemode enter

退出安全模式

hadoop dfsadmin -safemode leave

文件系统元数据的持久性

NameNode使用名为EditLog的事务日志来持久记录文件系统元数据发生的每一个变化。NameNode使用名为EditLog的事务日志来持久记录文件系统元数据发生的每一个变化,HA会将日志记录在JNS集群中。

NameNode将整个文件系统名称空间镜像(image)和文件块映射(Blockmap)的保存在4G内存中。

当NameNode启动时,它从磁盘读取FsImage和EditLog,将EditLog中的所有事务应用到FsImage的内存表示中,并将这个新版本刷新到磁盘上的新FsImage中。它可以截断旧的EditLog,因为它的事务已经被应用到持久的FsImage。这个过程被称为checkpoint。在当前的实现中,只有在NameNode启动时才会出现检查点。

DataNode将HDFS数据存储在本地文件系统的文件中。由于本地文件系统可能无法有效地支持单个目录中的大量文件,因此DataNode不会在同一目录中创建所有文件,相反,它使用启发式来确定每个目录的最佳文件数量并适当地创建子目录。

当DataNode启动时,它会扫描其本地文件系统,生成与这些本地文件相对应的所有HDFS数据块的列表,并将此报告发送给NameNode:这是Blockreport。

鲁棒性

HDFS三种常见的故障类型是NameNode故障,DataNode故障和网络分区,在出现故障时,HDFS也能可靠地存储数据

数据磁盘故障,心跳和重新复制

每个DataNode定期向NameNode发送一个Heartbeat消息。NameNode将没有最近Heartbeats的DataNode标记为死亡,并且不会将任何新的IO请求转发给它们。任何已经注册到死的DataNode的数据不再可用于HDFS。

DataNode死亡可能导致某些块的复制因子降到其指定值以下。NameNode不断跟踪哪些块需要复制,并在需要时启动复制。当出现这几种情况会启动重新复制:DataNode可能变得不可用,副本可能被破坏,DataNode上的硬盘可能失败。

集群rebalancing

如果DataNode上的可用空间低于某个阈值,则方案可能会自动将数据从一个DataNode移动到另一个DataNode。需要手动执行hadoop balancer [-threshold]操作

集群rebalancing

为保证从DataNode获取的数据块不是损坏(数据有可能会损坏)的,HDFS客户端软件会对HDFS文件的内容进行校验和检查。当客户端创建一个HDFS文件时,它会计算每个文件块的校验和,并将这些校验和存储在同一个HDFS名称空间的单独隐藏文件中。当客户端检索文件内容时,它会验证从每个DataNode收到的数据是否与存储在相关校验和文件中的校验和相匹配。如果没有,那么客户端可以选择从另一个具有该块的副本的DataNode中检索该块。

快照

快照支持在特定时刻存储数据副本。快照功能的一种用法可能是将损坏的HDFS实例回滚到先前已知的良好时间点。

文件操作

写流程

下面图中演示了写流程

客户端创建文件的请求不会立即到达NameNode。事实上,最初HDFS客户端将文件数据缓存到临时的本地文件中。应用程序写入被透明地重定向到这个临时的本地文件。当本地文件累积超过一个HDFS块大小的数据时,客户端联系NameNode。NameNode将文件名插入到文件系统层次结构中,并为其分配一个数据块。NameNode以DataNode的标识和目标数据块响应客户请求。然后,客户端将本地临时文件中的数据块刷新到指定的DataNode。当文件关闭时,临时本地文件中剩余的未刷新数据将被传输到DataNode。客户端然后告诉NameNode该文件已关闭。在此刻,NameNode将文件创建操作提交到持久性存储中。如果NameNode在文件关闭之前死亡,则文件丢失。

当本地文件累积完整的用户数据块时,客户端从NameNode中检索DataNode列表。该列表包含将承载该块的副本的DataNode。客户端然后将数据块刷新到第一个DataNode。第一个DataNode开始以小部分接收数据(chunk),将每个部分写入其本地存储库,并将该部分传输到列表中的第二个DataNode。第二个DataNode接着开始接收数据块的每个部分,将该部分写入其存储库,然后将该部分刷新到第三个DataNode。最后,第三个DataNode将数据写入其本地存储库。数据从一个DataNode流水线化到下一个。

读流程

下面图中演示了读流程

HA

hadoop2.x之后,Clouera提出了QJM/Qurom Journal Manager,这是一个基于Paxos算法实现的HDFS HA方案,它给出了一种较好的解决思路和方案,示意图如下:
这里写图片描述

下面先介绍每个组件的作用:
JN(Journal Manager):存储记录(EditLog),namenode对其读写
ZK(ZooKeeper):监听NameNode failure状态,选举Active NameNode,通过zkfc让zk和nn交互
FailoverController:主要包括三个组件:

  • HealthMonitor: 监控NameNode是否处于unavailable或unhealthy状态。当前通过RPC调用NN相应的方法完成
  • ActiveStandbyElector: 管理和监控自己在ZK中的状态
  • ZKFailoverController 它订阅HealthMonitor 和ActiveStandbyElector 的事件,并管理NameNode的状态

ZKFailoverController(zkfc): ZK客户端,主要有以下职责

  • 健康监测: 周期性的向它监控的NN发送健康探测命令,判断某个NameNode是否处于健康状态,如果机器宕机,心跳失败,那么zkfc就会标记它处于一个不健康的状态
  • zk会话管理:如果NN是健康的,zkfc就会在zookeeper中保持一个打开的会话,如果NameNode同时还是Active状态的,那么zkfc还会在Zookeeper中占有一个类型为短暂类型的”lock” znode,当这个NN挂掉时,这个znode将会被删除,然后备用的NN,将会得到这把锁,升级为主NN,同时标记状态为Active。当宕机的NN重新启动时,它会再次注册zookeper,发现已经有znode锁了,便会自动变为Standby状态,如此往复循环,保证高可靠,需要注意,目前仅仅支持最多配置2个NN
  • master选举:如果zkfc对应的nn是健康的,并且zkfc检测到当前没有节点持有lock znode,那它就会去获取这个锁,如果成功了,就表示赢得了选举,之后就是通过隔离(fence)机制隔离之前active nn,并将当前nn置为active状态

下面介绍下正常情况下ha的工作流程:

在典型的ha集群中,有两个NameNode,任何时间一个保持为active状态,另一个保持为standby状态,active状态的nn相应客户端的所有请求,而standby节点只是作为一个从节点,并在必要时保持足够的状态以提供快速故障切换(fast failover)

standby节点为了和active节点保持状态同步,两个节点都需要和JournalNodes进程同步。当active节点检测到名称空间(namespace)有变化,它就会持久化修改日志到jns中,standby时刻监听jns edit log的变化,并从jns中同步变化内容到本地。在failover事件发生后,在standby节点切换成active节点之前,需要读取从jns读取所有的edits,以保证名称空间(namespace)完全同步。

为了提供快速故障转移(fast failover),备用节点还需要知道有关于群集中块的位置的最新信息。为了实现这一点,DataNode配置了两个NameNode的信息,并发送块位置信息和心跳给两者。

jns在同一时刻,只允许单个nn节点作为writer能向jns写数据,另个nn只能读数据。

配置

一般的,可以按照下面的部署方式部署hadoop ha集群
这里写图片描述

一般我们将zookeeper集群单独部署,如果集群资源够的话,也将journalnode单独部署集群
通常ZK和JN都是部署奇数个节点(zn+1)
zkfc需要启动在namenode节点上

下面介绍与ha相关各个组件对应hadoop中的配置(hdfs-site.xml):

  • namenode
<!-- 配置nameservice ID -->
<property>
  <name>dfs.nameservices</name>
  <value>mycluster</value>
</property>
<!-- 配置namenode ID -->
<property>
  <name>dfs.ha.namenodes.mycluster</name>
  <value>nn1,nn2</value>
</property>
<!-- 配置namenode 相互监听的RPC地址 -->
<property>
  <name>dfs.namenode.rpc-address.mycluster.nn1</name>
  <value>machine1.example.com:8020</value>
</property>
<property>
  <name>dfs.namenode.rpc-address.mycluster.nn2</name>
  <value>machine2.example.com:8020</value>
</property>
<!-- 配置namenode HTTP 服务(ui界面) -->
<property>
  <name>dfs.namenode.http-address.mycluster.nn1</name>
  <value>machine1.example.com:50070</value>
</property>
<property>
  <name>dfs.namenode.http-address.mycluster.nn2</name>
  <value>machine2.example.com:50070</value>
</property>
  • JournalNodes
<!-- 指定NameNode的对JournalNode读写的URI -->
<property>
    <name>dfs.namenode.shared.edits.dir</name>
    <value>qjournal://node1.example.com:8485;node2.example.com:8485;node3.example.com:8485/mycluster</value>
</property>
<!-- 指定JournalNode在本地磁盘存放数据的位置 -->
<property>
  <name>dfs.journalnode.edits.dir</name>
  <value>/path/to/journal/node/local/data</value>
</property>
  • ZKFailoverController
<!-- 配置DFS客户端判断哪个namenode是active的java类 -->
<property>
  <name>dfs.client.failover.proxy.provider.mycluster</name>
  <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
  • 隔离机制

我们期望每次只有一个Active NameNode,当发生脑裂时(两个都是Active),由于使用QJM的时候要求只能有一个NameNode能写JournalNodes,因此不会对元数据造成损坏。但是,原来Active的NameNode发生failover,它还是会接收客户端的读请求,会导致请求失败直到该NameNode写JournalNodes失败后关闭。因此我们希望把不健康的NameNode服务给杀掉(这个过程就称为fence)。而下面这个配置就是配置了执行杀死原来Active NameNode服务的方法。这里面配置的所有方法都会被顺序的执行,最后返回结果即为fence过程的结果。如果fence执行成功,就把原来为Standby的NameNode的状态提升为Active。sshfence方法会通过ssh远程调用fuser命令去找到NameNode服务并杀死它。我们的目标是当发生failover时,不论如何,就算前面的sshfence执行失败(比如服务器上不存在fuser命令),依然把Standby节点的状态提升为Active,所以最后无论如何要配置一个shell(/bin/true),保证不论前面的方法执行的情况如何,最后fence过程返回的结果都为true。dfs.ha.fencing.ssh.private-key-files配置了ssh命令所需要用到的私钥。

<property>
      <name>dfs.ha.fencing.methods</name>
      <!-- 每个命令占一行 -->
      <value>
          sshfence
          shell(/bin/true)
      </value>
</property>
<!-- 使用sshfence隔离机制时需要ssh免登陆 -->
<property>
    <name>dfs.ha.fencing.ssh.private-key-files</name>
    <value>/home/exampleuser/.ssh/id_rsa</value>
</property>
<!-- 配置sshfence隔离机制超时时间 -->
<property>
    <name>dfs.ha.fencing.ssh.connect-timeout</name>
    <value>30000</value>
</property>

命令

ha相关指令

Usage: haadmin
    [-transitionToActive <serviceId>]
    [-transitionToStandby <serviceId>]
    [-failover [--forcefence] [--forceactive] <serviceId> <serviceId>]
    [-getServiceState <serviceId>]
    [-checkHealth <serviceId>]
    [-help <command>]
  • transitionToActive and transitionToStandby - 切换Active或Standby状态
  • failover - initiate a failover between two NameNodes
  • getServiceState - determine whether the given NameNode is Active or Standby
  • checkHealth - check the health of the given NameNode

参考

官方HA文档2.7.1
官方HDFS文档
大数据集群环境搭建——HDFS HA篇
hadoop2.5.2学习及实践笔记(三)—— HDFS概念及体系结构
Name node is in safe mode.(NameNode处于安全模式)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值