Hadoop生态一---分布式文件系统HDFS

分布式文件系统: 统一管理分布在集群上的文件系统
设计思想
分而治之:将大文件、大批量文件,分布式存放在大量服务器上,以便于采取分而治之的方式对海量数据进行运算分析;

在大数据系统中作用:
为各类分布式运算框架(如:mapreduce,spark,tez,……)提供数据存储服务

重点概念:文件切块,副本存放,元数据

HDFS的概念和特性

  • HDFS中的文件在物理上是分块存储(block),块的大小可以通过配置参数( dfs.blocksize)来规定,默认大小在hadoop2.x版本中是128M,老版本中是64M

  • HDFS文件系统会给客户端提供一个统一的抽象目录树,客户端通过路径来访问文件,形如:hdfs://namenode:port/dir-a/dir-b/dir-c/file.data

  • 目录结构及文件分块信息(元数据)的管理由namenode节点承担——namenode是HDFS集群主节点,负责维护整个hdfs文件系统的目录树,以及每一个路径(文件)所对应的block块信息(block的id,及所在的datanode服务器)

  • 文件的各个block的存储管理由datanode节点承担---- datanode是HDFS集群从节点,每一个block都可以在多个datanode上存储多个副本(副本数量也可以通过参数设置dfs.replication)

  • HDFS是设计成适应一次写入,多次读出的场景,且不支持文件的修改

HDFS的工作机制

  • HDFS集群分为两大角色:NameNode、DataNode (Secondary Namenode)

  • NameNode负责管理整个文件系统的元数据

  • DataNode 负责管理用户的文件数据块

  • 文件会按照固定的大小(blocksize)切成若干块后分布式存储在若干台datanode上

  • 每一个文件块可以有多个副本,并存放在不同的datanode上

  • Datanode会定期向Namenode汇报自身所保存的文件block信息,而namenode则会负责保持文件的副本数量

  • HDFS的内部工作机制对客户端保持透明,客户端请求访问HDFS都是通过向namenode申请来进行

  • Secondary NameNode 用来监控 HDFS 状态的辅助后台程序,每隔一段时间获取 HDFS 元数据的快照。最主要作用是辅助 NameNode 管理元数据信息。

HDFS安全模式

安全模式是hadoop的一种保护机制,用于保证集群中的数据块的安全性。当集群启动的时候,会首先进入安全模式。当系统处于安全模式时会检查数据块的完整性。

假设我们设置的副本数(即参数dfs.replication)是3,那么在datanode上就应该有3个副本存在,假设只存在2个副本,那么比例就是2/3=0.666。hdfs默认的副本率0.999。我们的副本率0.666明显小于0.999,因此系统会自动的复制副本到其他dataNode,使得副本率不小于0.999。如果系统中有5个副本,超过我们设定的3个副本,那么系统也会删除多于的2个副本。

在安全模式状态下,文件系统只接受读数据请求,而不接受删除、修改等变更请求。在,当整个系统达到安全标准时,HDFS自动离开安全模式。

HDFS 的 block 块和副本机制

HDFS 将所有的文件全部抽象成为 block 块来进行存储,不管文件大小,全部一视同仁都是以 block 块的统一大小和形式进行存储,方便我们的分布式文件系统对文件的管理。

通常 DataNode 从磁盘中读取块,但对于访问频繁的文件,其对应的块可能被显示的缓存在 DataNode 的内存中,以堆外块缓存的形式存在。默认情况下,一个块仅缓存在一个DataNode的内存中,当然可以针对每个文件配置DataNode的数量。
作业调度器通过在缓存块的DataNode上运行任务,可以利用块缓存的优势提高读操作的性能。

HDFS写数据流程

客户端要向HDFS写数据,首先要跟namenode通信以确认可以写文件并获得接收文件block的datanode,然后,客户端按顺序将文件逐个block传递给相应datanode,并由接收到block的datanode负责向其他datanode复制block的副本

详细步骤如下:

  1. Client 发起文件上传请求,通过 RPC 与 NameNode 建立通讯,namenode检查目标文件是否已存在,父目录是否存在

  2. namenode返回是否可以上传

  3. client请求第一个 block该传输到哪些datanode服务器上

  4. namenode返回可用的datanode服务器,如ABC

  5. client请求3台dn中的一台A上传数据(本质上是一个RPC调用,建立pipeline),A收到请求会继续调用B,然后B调用C,将整个pipeline建立完成,逐级返回客户端

  6. client开始往A上传第一个block(先从磁盘读取数据放到一个本地内存缓存),以packet为单位,A收到一个packet就会传给B,B传给C;A每传一个packet会放入一个应答队列等待应答

  7. 数据被分割成一个个 packet 数据包在 pipeline 上依次传输,在 pipeline 反方向上, 逐个发送 ack(命令正确应答),最终由 pipeline 中第一个 DataNode 节点 A 将 pipelineack 发送给 Client;

  8. 当一个block传输完成之后,client再次请求namenode上传第二个block的服务器。

HDFS读数据流程

客户端将要读取的文件路径发送给namenode,namenode获取文件的元信息(主要是block的存放位置信息)返回给客户端,客户端根据返回的信息找到相应datanode逐个获取文件的block并在客户端本地进行数据追加合并从而获得整个文件

详细步骤如下:

  1. Client向NameNode发起RPC请求,来确定请求文件block所在的位置

  2. NameNode会视情况返回文件的部分或者全部block列表,对于每个block,NameNode 都会返回含有该 block 副本的 DataNode 地址

  3. Client 选取排序靠前的 DataNode 来读取 block,如果客户端本身就是DataNode,那么将从本地直接获取数据(短路读取特性)

  4. 底层上本质是建立 Socket Stream(FSDataInputStream),重复的调用父类 DataInputStream 的 read 方法,直到这个块上的数据读取完毕;

  5. 当读完列表的 block 后,若文件读取还没有结束,客户端会继续向NameNode 获取下一批的 block 列表;

  6. 读取完一个 block 都会进行 checksum 验证,如果读取 DataNode 时出现错误,客户端会通知 NameNode,然后再从下一个拥有该 block 副本的DataNode 继续读。

  7. read 方法是并行的读取 block 信息,不是一块一块的读取;NameNode 只是返回Client请求包含块的DataNode地址,并不是返回请求块的数据;

  8. 最终读取来所有的 block 会合并成一个完整的最终文件。

NameNode工作机制

namenode职责:

  • 负责客户端请求的响应

  • 元数据的管理(查询,修改)

元数据管理

namenode对数据的管理采用了三种存储形式:

  • 内存元数据(NameSystem)

  • 磁盘元数据镜像文件

  • 数据操作日志文件(可通过日志运算出元数据)

元数据存储机制

  1. 内存中有一份完整的元数据(内存meta data)

  2. 磁盘有一个“准完整”的元数据镜像(fsimage)文件(在namenode的工作目录中)

  3. 用于衔接内存metadata和持久化元数据镜像fsimage之间的操作日志(edits文件)

注:当客户端对hdfs中的文件进行新增或者修改操作,操作记录首先被记入edits日志文件中,当客户端操作成功后,相应的元数据会更新到内存meta.data中

元数据的checkpoint

每隔一段时间,会由secondary namenode将namenode上积累的所有edits和一个最新的fsimage下载到本地,并加载到内存进行merge(这个过程称为checkpoint)

Secondary NameNode

Secondary namenode的职责是合并namenode的edit logs到fsimage文件中。

每隔一段时间,会由secondary namenode将namenode上积累的所有edits和一个最新的fsimage下载到本地,并加载到内存进行merge(这个过程称为checkpoint)

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

但是只能恢复大部分数据,并不能恢复全部数据,因为有些数据可能还没做checkpoint

checkpoint操作的触发条件配置参数

dfs.namenode.checkpoint.check.period=60  #检查触发条件是否满足的频率,60秒

dfs.namenode.checkpoint.dir=file://${hadoop.tmp.dir}/dfs/namesecondary

#以上两个参数做checkpoint操作时,secondary namenode的本地工作目录

dfs.namenode.checkpoint.edits.dir=${dfs.namenode.checkpoint.dir}



dfs.namenode.checkpoint.max-retries=3  #最大重试次数

dfs.namenode.checkpoint.period=3600  #两次checkpoint之间的时间间隔3600秒

dfs.namenode.checkpoint.txns=1000000 #两次checkpoint之间最大的操作记录


  1. Secondary namenode请求是否需要checkpoint

  2. 得到namenode响应后,Secondary namenode请求checkpoint

  3. Namenode滚动当前正在写的edit文件,该文件为待合并状态,也会生成新的edits.inprogress文件,后续的修改日志将写入该文件中

  4. Secondary namenode将待合并的edits文件和fsimage文件一起下载到Secondary namenode本地。

  5. Secondary namenode将fsimage文件和edits文件加载到内存进行合并。dump成新的fsimage文件fsimage.chkpoint。

  6. Secondary namenode将fsimage.chkpoint上传到namenode,并重命名为fsimage。

checkpoint的附带作用

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

DataNode工作机制

Datanode职责:

  • 存储管理用户的文件块数据

  • 定期向namenode汇报自身所持有的block信息(通过心跳信息上报)(这点很重要,因为,当集群中发生某些block副本失效时,集群如何恢复block初始副本数量的问题)

HDFS HA机制

HA即为High Availability(高可用),用于解决NameNode单点故障的问题。该特性通过以热备的方式为NameNode提供一个备用者,一旦主NameNode出现故障,可以很快切换到备用的NameNode,从而实现对外提供服务。

HA是为了解决单点问题,通过JN集群共享状态,通过ZKFC 选举active,监控状态,自动备援。

Active Namenode将数据写入共享文件管理系统,而StandbyNamenode监听该系统,一旦发现有新数据写入,则读取这些数据,并加载到自己内存中,以保证自己内存状态与Active NameNode保持基本一致。如此,在紧急情况下standby便可快速切为active namenode。

自动故障转移机制:

  1. active Namenode宕机(假死)。

  2. active Namenode zkfc检测到假死

  3. 通知另一台namenode的zkfc

  4. 另一台机机器强行杀死之前的active namenode

  5. 激活standby namenode,切为active状态

脑裂

假设NameNode1当前为Active状态,NameNode2当前为Standby状态。如果某一时刻NameNode1对应的ZKFailoverController进程发生了"假死"现象,那么Zookeeper服务端会认为NameNode1进入Active状态。但是此时NameNode1可能仍然处于Active状态正常运行,这样NameNode1和NameNode2都处于Active状态,都可以对外提供服务。这样的情况称为脑裂。

解决方法:fencing(隔离),想办法把旧的Active NameNode隔离起来,使它不能正常对外提供服务。
在进行fencing的时候,会执行以下的操作

  1. 首先尝试调用这个旧 Active NameNode 的 HAServiceProtocol RPC 接口的 transitionToStandby 方法,看能不能把它转换为 Standby 状态。

  2. 如果 transitionToStandby 方法调用失败,那么就执行 Hadoop 配置文件之中预定义的隔离措施,Hadoop 目前主要提供两种隔离措施,通常会选择 sshfence:

    • sshfence:通过 SSH 登录到目标机器上,执行命令 fuser 将对应的进程杀死;
    • shellfence:执行一个用户自定义的 shell 脚本来将对应的进程隔离。
posted @ 2021-10-20 20:01  cos晓风残月  阅读(203)  评论(0编辑  收藏  举报