Day 01(02): 精读HDFS概念

发布于:2025-09-01 ⋅ 阅读:(23) ⋅ 点赞:(0)

目标:建立对大数据生态的整体认知,理解HDFS和MapReduce的核心思想。

9:30-10:30:【概念学习】精读“HDFS”概念。搞懂块(Block)副本(Replication)NameNodeDataNode各自的作用。

目录

HDFS 概述

一、HDFS 简介

二、HDFS 核心原理与架构

三、HDFS 的优点

四、HDFS 的缺点与局限性

五、操作与运维

HDFS 系统架构与核心原理

一、核心架构:主从 (Master-Slave) 结构

二、数据存储机制

三、读写流程(以写入为例)

四、关键机制:心跳 (Heartbeat)

五、元数据 (Metadata) 管理

HDFS 数据存储细节

一、数据块 (Block) - 核心存储单元

二、副本放置策略 (Replica Placement Policy)

三、数据在磁盘上的存储格式

HDFS 元数据 (Metadata) 存储与合并机制

一、元数据内容与存储挑战

二、持久化方案:FsImage + Edits

三、元数据合并的必要性与机制

四、合并的执行者:两种模式

模式一:无高可用 (Non-HA) 模式 - SecondaryNameNode

模式二:高可用 (HA) 模式 - StandbyNameNode & JournalNodes

五、磁盘上的文件表示

HDFS 文件读写流程总结

一、文件写入 (Write) 流程

二、文件读取 (Read) 流程

核心设计思想

HDFS 安全模式 (Safe Mode) 总结

一、什么是安全模式?

二、为什么需要安全模式?

三、进入/退出安全模式的条件(核心机制)

四、导致安全模式的常见原因

五、排查与处理建议

HDFS 高可用 (High Availability) 

一、单NameNode架构的缺陷

二、解决内存上限:联邦 (Federation)

三、解决单点故障:高可用 (HA)

四、HA的实现:依赖两个关键组件

1. JournalNodes (JN) - 共享元数据存储

2. ZooKeeper (ZK) - 分布式协调与故障转移

五、总结:HA如何工作

HDFS 操作命令

一、Shell 命令行操作 (针对运维/用户)

二、REST API 操作 (针对开发)

总结与对比


HDFS概述_哔哩哔哩_bilibili

HDFS 概述

一、HDFS 简介
  • 全称:Hadoop Distributed File System (Hadoop分布式文件系统)。

  • 起源:是基于谷歌的GFS论文思想实现的开源项目。

  • 地位:是Hadoop的核心三大组件(HDFS, MapReduce, YARN)之一,是整个Hadoop生态圈的基石。目前在大数据领域地位无可替代。

二、HDFS 核心原理与架构
  • 重点:需要掌握其架构部分。

  • 设计目标:存储和管理海量数据。

  • 关键角色

    • 管理节点 (NameNode):负责管理文件系统的元数据(如文件名、文件目录结构、文件分块信息、块存储位置等)。这些元数据存储在内存中,因此其内存容量限制了集群处理小文件的能力。

    • 数据节点 (DataNode):负责实际存储数据块。

三、HDFS 的优点
  1. 海量数据存储:能够存储PB级别的数据。

  2. 高容错性与可靠性

    • 数据通过多副本冗余机制存储(默认3份)。

    • 即使某个DataNode宕机,数据也不会丢失,可以从其他副本恢复。

    • 可以构建在廉价的商用服务器上,通过软件机制弥补硬件可靠性的不足,从而降低构建成本。

  3. 适合批处理

    • 遵循“移动计算而非移动数据”的原则。

    • 能够将计算任务(MapReduce)调度到数据所在的节点上进行,极大减少了数据网络传输开销,非常适合大规模离线批处理场景。

  4. 高可扩展性:可以通过简单地增加机器来线性扩展集群的存储和计算能力。

四、HDFS 的缺点与局限性
  1. 高延迟访问:设计目标是高吞吐量,而非低延迟。不适合需要毫秒级响应的交互式查询或实时处理(如HBase更适合此场景)。

  2. 不支持并发写入:一个文件同一时间只能由一个写入者操作,写入是串行的。

  3. 不适合存储大量小文件

    • 根本原因:每个文件的元数据都会占用NameNode的固定内存。大量小文件会快速耗尽NameNode内存,导致集群无法管理更多文件。

    • 性能影响:处理大量小文件时,计算框架(如MapReduce)会生成过多的任务,导致任务调度时间远大于数据处理时间,效率极低。

  4. 不支持文件随机修改:仅支持追加写入 (Append-only),不支持在文件任意位置进行修改。这符合其一次写入、多次读取的流式数据访问模型。

五、操作与运维
  • 后续章节会介绍HDFS的常用操作命令和日常运维管理方法。


核心要点记忆:HDFS的核心是一个为海量数据、离线批处理而设计的分布式文件系统,其多副本机制保证了可靠性,但其元数据存储在NameNode内存的特点导致了它怕小文件高延迟的主要缺点。

HDFS架构_哔哩哔哩_bilibili

主从架构

数据写入流程

HDFS 系统架构与核心原理

一、核心架构:主从 (Master-Slave) 结构

HDFS采用典型的主从架构,由一个或多个主节点(NameNode)和多个从节点(DataNode)组成。

  • 主节点 (NameNode - Active)

    • 角色:集群的“大脑”和“管理者”。

    • 核心职能

      1. 管理元数据 (Metadata):存储和管理文件系统的命名空间(如文件名、目录结构、文件属性等)。

      2. 接收客户端请求:处理来自客户端的所有读写请求。

      3. 管理数据块映射:记录每个文件对应的数据块(Block)列表,以及每个数据块所在的DataNode信息(此部分信息由DataNode上报,NameNode在内存中动态维护)。

      4. 调度集群:通过心跳机制监控和管理所有DataNode。

  • 从节点 (DataNode)

    • 角色:集群的“劳动力”,负责实际的数据存储。

    • 核心职能

      1. 存储数据块 (Block):在本地文件系统中存储和管理真实的数据块。

      2. 执行数据读写:根据NameNode的指令或客户端的直接请求,进行数据的读写操作。

      3. 定期心跳上报 (Heartbeat)每隔3秒向NameNode发送一次心跳,汇报自身的健康状态所存储的数据块列表

      4. 执行指令:接收并执行来自NameNode的创建、删除、复制数据块等命令。

  • 主节点 (NameNode - Standby)

    • 角色高可用 (HA) 架构中的备用主节点

    • 核心职能

      1. 实时与Active NameNode同步元数据

      2. 当Active NameNode发生故障时,自动切换为Active状态,接管集群管理职责,确保服务不中断。

二、数据存储机制
  1. 分块存储 (Block)

    • 文件在上传时会被切分成固定大小的数据块 (Block)

    • 默认块大小为 128MB(可根据配置调整)。

    • 最后一个块的大小可能小于128MB。

    • 分块的好处:简化存储设计、支持大文件存储、便于备份和计算本地化。

  2. 多副本冗余 (Replication)

    • 每个数据块会被复制为多个副本(默认3个)。

    • 这些副本被分布存储在不同的DataNode上。

    • 目的:提供极高的容错性数据可靠性。即使某个DataNode宕机,数据也不会丢失,可以从其他副本恢复。

三、读写流程(以写入为例)
  1. 客户端发起文件上传请求(如10GB的 file1)。

  2. 客户端将文件按128MB切分成多个Block(如80个)。

  3. 客户端与NameNode通信,获取每个Block应存入哪些DataNode的地址。

  4. 客户端根据指令,将各个Block并行地写入到不同的DataNode上。

  5. DataNode之间会自动完成副本的复制(Pipeline写入)。

  6. 写入完成后,NameNode在内存中更新元数据,记录 file1 由哪些Block组成。

  7. 各个DataNode通过心跳,定期向NameNode汇报自己存储了哪些Block,从而让NameNode维护完整的“Block->DataNode”映射关系。

四、关键机制:心跳 (Heartbeat)
  • 作用:DataNode与NameNode之间的通信纽带健康检查机制

  • 内容:DataNode每隔3秒向NameNode发送心跳包,包涵:

    • 自身状态(是否存活)。

    • 所存储的所有数据块列表。

  • 重要性

    • 判断节点存活:如果NameNode长时间(如10分钟) 未收到某个DataNode的心跳,则判定该节点宕机。

    • 触发容错:一旦判定DataNode宕机,NameNode会启动数据恢复流程,将其上的数据块从其他副本重新复制到健康的DataNode上,始终维持预设的副本数(如3个)。

五、元数据 (Metadata) 管理
  • 存储内容

    • 核心且持久化的:文件系统的目录树结构、文件名称、属性、文件对应的Block ID列表

    • 动态维护的Block存储在哪些DataNode上(这部分信息由DataNode上报,储在NameNode内存中,不会持久化到磁盘)。

  • 存储位置:全部元数据(包括动态部分)都存储在NameNode的内存,以保证极高的访问速度。

  • 由此带来的限制:正是由于所有元数据都在内存中,大量小文件会快速耗尽NameNode内存,成为HDFS的主要瓶颈之一


总结:HDFS通过主从架构分块存储多副本机制心跳汇报实现了海量数据的高可靠、高吞吐量存储。其设计核心是牺牲低延迟来换取高吞吐容错能力非常适合离线大数据处理场景。NameNode的内存是集群扩展性的关键限制因素。

HDFS数据存储Block_哔哩哔哩_bilibili

HDFS 数据存储细节

一、数据块 (Block) - 核心存储单元
  • 定义:Block是HDFS中最小的数据存储单元。

  • 拆分规则

    • 文件在上传时会被按固定大小切分成多个Block

    • 默认大小为 128MB

    • 这是一个拆分标准,而非必须填满的固定容器。最后一个Block的大小就是剩余数据的大小(例如,一个129MB的文件会被拆分成一个128MB的Block和一个1MB的Block)。

  • 块大小配置

    • 块大小是可配置的,但企业中通常不建议调整

    • 调小的弊端:会产生更多Block,导致NameNode元数据压力增大(小文件问题),计算任务调度开销增加。

    • 调大的弊端:单个计算任务处理的数据量变大,任务运行时间变长,可能降低集群的整体并发处理能力。

二、副本放置策略 (Replica Placement Policy)

为了保证数据的可靠性和访问效率,每个Block默认会有3个副本,并按照以下策略分布在不同的DataNode上:

  1. 第一个副本

    • 优先存放在离客户端最近的DataNode上。

    • 如果“距离”相同(例如客户端在集群外),则选择当前最空闲的DataNode。

  2. 第二个副本

    • 存放在与第一个副本不同机架 (Rack) 上的某一个DataNode上。

    • 目的:防止整个机架出现故障(如交换机或电源故障)导致数据不可用,增强容错能力。

    • 同样会选择该机架上最空闲的节点。

  3. 第三个副本

    • 存放在与第二个副本相同机架上的另一个DataNode上。

    • 原因:跨两个机架已经提供了足够的容错能力。将第三个副本放在同一机架内,可以减少跨机架传输的网络开销,加快副本写入速度,同时也能保证数据安全。

总结:该策略完美平衡了可靠性(跨机架容灾)、写入带宽(减少跨机架传输)和读取性能(副本分布在不同位置)。

三、数据在磁盘上的存储格式

在DataNode服务器的本地文件系统上,Block被存储为物理文件。

  • 存储目录:由HDFS配置文件(如 hdfs-site.xml)中的 dfs.datanode.data.dir 参数指定,可以配置多个目录以利用多块磁盘。

  • 文件结构

    • 每个Block对应两个物理文件:

      1. blk_<id>:这是存储实际文件内容的数据文件(如 blk_1073742825)。

      2. blk_<id>.meta:这是对应数据文件的元信息文件(如 blk_1073742825.meta)。

  • Meta文件内容

    • 该文件与NameNode管理的全局元数据无关

    • 它存储的是针对这个Block数据本身的校验信息,包括:

      • 版本信息

      • 数据类型

      • 每个数据块的校验和 (Checksum),用于检测数据是否损坏。

      • 一些其他块属性。


核心要点:HDFS通过固定大小的块来简化管理和处理海量文件,通过智能的跨机架副本策略来保证数据的超高可靠性,并在磁盘上通过数据文件+校验文件的形式来确保存储数据的完整性。

hdfs-site.xml

  • 文件路径hdfs-site.xml 文件位于 Hadoop 安装目录的 etc/hadoop/ 子目录下。

    • 例如,如果你的 Hadoop 安装在 /usr/local/hadoop,那么该文件的完整路径就是:/usr/local/hadoop/etc/hadoop/hdfs-site.xml

  • 谁使用它:这个配置文件是 HDFS 守护进程的专用配置。

    • NameNode 和 DataNode 进程在启动时都会读取这个文件来获取配置信息。

    • 你需要在集群中的所有节点(无论是NameNode还是DataNode)上都部署这个配置文件,并且通常保持内容一致,以确保所有节点对HDFS的行为有相同的理解。

每个DataNode节点上都必须有 hdfs-site.xml 配置文件,并且其中都定义了 dfs.datanode.data.dir 这个参数。这是HDFS集群配置管理的基本要求。

为什么每个DataNode都需要这个文件?

  1. 独立的本地配置:每个DataNode进程在启动时,需要读取本地的 hdfs-site.xml 文件来获取它自己应该如何工作的指令。其中最关键的一条指令就是:“我应该把数据块(Block)存到本机的哪个(些)目录里?” 这个答案对于集群中的每个DataNode来说通常是不同的,因为它取决于各自服务器的磁盘挂载情况。

  2. 配置一致性:虽然 dfs.datanode.data.dir 的可能因节点而异,但配置文件本身和其他大多数参数(如网络端口、RPC设置等)在集群范围内需要保持一致,以确保所有节点能够相互通信并遵循相同的规则。

工作流程是怎样的?

  1. 准备配置:管理员会在其中一台机器上配置好 hdfs-site.xml(以及 core-site.xml 等)文件。

  2. 分发配置:使用像 Ansible、Puppet、Chef 这样的自动化配置管理工具,或者直接用 scp/rsync 命令,将这些配置文件分发到集群中所有节点的相同目录$HADOOP_HOME/etc/hadoop/)下。

  3. 个性化配置:对于 dfs.datanode.data.dir 参数,如果需要为不同节点指定不同的目录(例如,某个节点有4块磁盘,另一个节点有6块),管理员可以通过上述工具模板化地生成每个节点特定的配置,或者确保所有节点磁盘挂载点规划一致后使用相同的配置值。

  4. 启动服务:在每个节点上启动DataNode服务。每个DataNode进程都会读取本机上的 hdfs-site.xml 文件,找到 dfs.datanode.data.dir 参数指定的路径,然后开始使用这些目录来存储和读取数据块。

举个例子

假设你有一个3个节点的集群:dn01dn02dn03

  • dn01 服务器有4块磁盘,挂载在 /disk1/disk2/disk3/disk4

  • dn02 和 dn03 服务器有2块磁盘,挂载在 /data1/data2

那么,每个节点本地的 hdfs-site.xml 中 dfs.datanode.data.dir 的配置可能是:

  • 在 dn01 上:

    <property>
      <name>dfs.datanode.data.dir</name>
    <value>/disk1/hdfs/data,/disk2/hdfs/data,/disk3/hdfs/data,/disk4/hdfs/data</value>
    </property>
  • 在 dn02 和 dn03 上:

    <property>
      <name>dfs.datanode.data.dir</name>
      <value>/data1/hdfs/data,/data2/hdfs/data</value>
    </property>

总结

项目 说明
配置文件位置 每个节点的 $HADOOP_HOME/etc/hadoop/hdfs-site.xml
参数 dfs.datanode.data.dir
必要性 每个DataNode都必须有,因为它指示了该特定节点存储数据的本地路径
通常因节点而异,取决于该服务器的磁盘数量挂载点
配置管理 通过自动化工具(Ansible、Puppet、Chef等)分发和管理,确保每个节点获得正确一致的配置。

所以,每个DataNode节点上都有一份 hdfs-site.xml 文件,并且其中的 dfs.datanode.data.dir 参数指导着该节点如何使用本地的存储空间。

HDFS元数据存储_哔哩哔哩_bilibili

HDFS 元数据 (Metadata) 存储与合并机制

一、元数据内容与存储挑战
  • 存储内容:NameNode内存中存储两大核心元数据:

    1. 核心元数据:文件系统的目录树结构、文件属性、以及文件被拆分成了哪些Block(Block ID列表)。这部分信息至关重要,必须持久化

    2. 动态映射信息每个Block存储在哪些DataNode上。这部分信息由DataNode定期上报,NameNode在内存中动态维护,不需要持久化(丢失后可自动恢复)。

  • 存储挑战:内存中的数据“断电易失”。必须将关键元数据(核心元数据)持久化到磁盘,否则NameNode重启后整个文件系统将无法恢复。

二、持久化方案:FsImage + Edits

为了解决既要持久化又要保证高性能的矛盾,HDFS采用了“镜像文件 + 操作日志” 的方案。

  1. FsImage (镜像文件)

    • 内容:某一时刻完整的HDFS文件系统元数据(核心元数据)的快照。

    • 特点:是一个完整的检查点,不支持增量更新。直接修改FsImage效率极低(随机写)。

  2. Edits (编辑日志)

    • 内容:记录自最新FsImage之后,所有对元数据的更改操作(如创建文件、删除块等)。以日志形式顺序追加写入。

    • 特点只追加,不修改。顺序写的性能远高于随机写,极大减轻了NameNode的磁盘I/O压力。

  3. 恢复流程

    • NameNode启动时,先将FsImage加载到内存,形成基础的元数据状态。

    • 然后按顺序重放 (Replay) Edits日志中的所有操作,将内存中的元数据状态更新到最新。

    • 最后,接收DataNode的心跳汇报,重建“Block->DataNode”的映射关系。

三、元数据合并的必要性与机制
  • 问题:如果Edits日志无限增长,会导致:

    • 磁盘空间被大量占用。

    • NameNode重启时间极长(需要重放巨量的Edits日志),服务不可用时间无法接受。

  • 解决方案:必须定期将Edits日志中的操作合并到FsImage中,生成新的FsImage,并清空或截断旧的Edits日志。这个过程称为 Checkpoint(检查点)

四、合并的执行者:两种模式
模式一:无高可用 (Non-HA) 模式 - SecondaryNameNode
  • 角色:一个独立的、非备用的守护进程。它的唯一职责就是协助NameNode执行Checkpoint

  • 工作流程

    1. 触发:定期(默认1小时)或Edits日志大小达到阈值(默认64MB)时触发。

    2. 下载:从NameNode下载当前的FsImage和Edits日志。

    3. 合并:在本地加载FsImage并重放Edits,生成新的合并后的FsImage(通常命名为 fsimage.ckpt

    4. 上传:将新的FsImage上传回NameNode。

    5. 切换:NameNode用新的FsImage替换旧的,并开始将新的元数据操作写入一个新的Edits日志(如 edits.new -> edits)。

模式二:高可用 (HA) 模式 - StandbyNameNode & JournalNodes
  • 角色

    • Standby NameNode:Active NameNode的热备节点。除了准备接管服务,也承担了Checkpoint的工作

    • JournalNodes (JN):一个由奇数台(通常为3或5台)节点组成的独立集群,用于共享存储Edits日志

  • 工作流程

    1. 共享日志:Active NameNode将元数据更改操作(Edits)同时写入本地和大多数(半数以上)JournalNodes。

    2. 同步:Standby NameNode持续地从JN集群拉取Edits,并在自身内存中重放,从而保持与Active NameNode的元数据状态近乎实时同步。

    3. 合并:Standby NameNode定期执行Checkpoint,将累积的Edits合并到FsImage中,生成新的FsImage(此过程在Standby节点本地完成)。

    4. 持久化:Standby NameNode将新的FsImage持久化到本地磁盘(FsImage存储在本地是安全且高效的)。

  • 为何Edits不能只存本地?

    • 在HA模式下,如果Edits只存储在Active NameNode本地,当其宕机时,Standby NameNode无法获取最新的Edits日志,从而导致元数据不一致,无法正确接管服务。共享存储(JN)确保了Edits的高可用性

五、磁盘上的文件表示

在NameNode配置的元数据目录(dfs.namenode.name.dir)中,你会看到类似以下文件,它们体现了合并和滚动更新的过程:

  • fsimage_0000000000000000019:合并后生成的FsImage文件,数字是事务ID(Transaction ID),表示已包含到此ID为止的所有更改。

  • fsimage_0000000000000000019.md5:对应FsImage的校验文件。

  • edits_0000000000000000020-0000000000000000021:已被合并的旧Edits段文件(可安全删除)。

  • edits_inprogress_0000000000000000022:当前正在被写入的最新Edits文件

最新的元数据状态 = 最新的FsImage + 最新的edits_inprogress_...文件


核心结论:HDFS通过 FsImage(全量快照) 和 Edits(增量日志) 的组合,高效且可靠地管理元数据。通过定期合并(Checkpoint) 来控制日志大小,确保快速恢复。在非HA模式下,由SecondaryNameNode执行合并;在HA模式下,由StandbyNameNode执行合并,且Edits日志通过JournalNodes集群共享,以实现元数据的高可用和故障自动切换。

HDFS读写流程_哔哩哔哩_bilibili

写操作

切分数据库是在客户端进行的

读文件

HDFS 文件读写流程总结

一、文件写入 (Write) 流程
  1. 客户端发起请求

    • 客户端向NameNode发起请求,请求上传一个文件(如300MB的/tmp/file1)。

    • NameNode执行权限和目录检查。通过后,告知客户端允许上传。

  2. 客户端拆分文件

    • 在客户端本地,将文件按默认128MB的大小拆分成多个Block。

    • 示例:300MB文件被拆分成Block1(128MB)、Block2(128MB)、Block3(44MB)。

    • 优点:拆分工作在客户端进行,减轻了HDFS集群的压力。

  3. 上传单个Block(Pipeline写入)

    • 客户端逐个上传Block。以上传Block1为例:

      • a. 请求分配DataNode:客户端向NameNode请求上传Block1。

      • b. 选择DataNode:NameNode根据副本放置策略,返回三个适合存储该Block的DataNode列表(如DN1, DN2, DN3)。

      • c. 建立Pipeline:客户端与这三个DataNode建立Pipeline(管道) 连接(Client -> DN1 -> DN2 -> DN3)。

      • d. 传输数据:客户端将Block1的数据以Packet(数据包) 为单位流入Pipeline。

      • e. 流水线复制

        • DN1收到一个Packet后,会将其存到本地内存,同时立刻将其转发给DN2。

        • DN2做同样操作,收到后存内存并转发给DN3。

        • DN3将Packet存入本地内存。

      • f. 持久化与ACK:各个DataNode会异步地将内存中的Packet写入本地磁盘

      • g. 成功确认:确认过程沿Pipeline反向进行

        • DN3完成磁盘写入后,向DN2发送一个成功ACK。

        • DN2(在自身完成写入且收到DN3的ACK后) 向DN1发送ACK。

        • DN1(在自身完成写入且收到DN2的ACK后) 向客户端发送最终的ACK,宣告Block1写入成功。

  4. 循环上传

    • 客户端收到Block1的成功信号后,开始按相同流程上传Block2,然后是Block3。

  5. 最终确认

    • 所有Block都上传成功后,客户端通知NameNode。

    • NameNode才在内存中生成最终的元数据,记录文件/tmp/file1由哪些Block组成,以及每个Block的副本位置(由DataNode心跳上报补充)。


二、文件读取 (Read) 流程
  1. 客户端发起请求

    • 客户端向NameNode发起请求,请求下载文件(如/tmp/file1)。

    • NameNode进行权限校验。通过后,准备返回元数据。

  2. 返回元数据

    • NameNode从内存中查询到文件/tmp/file1的元数据,包括:

      • 文件由哪些Block构成(如Block1, Block2, Block3)。

      • 每个Block的所有副本所在的DataNode列表(如Block1在DN5, DN8, DN1上)。

    • 关键优化:NameNode会贴心地将每个Block的DataNode列表按照与客户端的网络拓扑距离进行排序(最近的在最前),以优化读取性能。

  3. 客户端直接读取数据

    • 客户端拿到元数据后,直接与存储Block的DataNode建立连接(不再通过NameNode中转)。

    • 对于每个Block,客户端都默认选择排序列表中最靠前(即最近) 的DataNode进行读取。

    • 示例:读取Block1时,优先连接距离最近的DN5。

  4. 并行读取与合并

    • 客户端可以并行地从多个DataNode下载不同的Block。

    • 所有Block下载到客户端本地后,客户端将其合并成完整的原始文件(如file1),并返回给用户。


核心设计思想
  • 减轻主节点压力:读写数据的核心流程(数据传输)都在客户端和DataNode之间直接进行,NameNode只负责元数据管理和调度,避免成为性能瓶颈。

  • 数据本地化 (Data Locality):计算任务(如MapReduce)会优先被调度到存有相关数据的DataNode上执行,遵循“移动计算比移动数据更划算”的原则。

  • 高吞吐量:通过大Block设计、Pipeline流水线传输和客户端并行读取,最大化数据传输的吞吐量,而非追求低延迟。

  • 容错机制:读写过程中任何DataNode失败,客户端都会自动尝试列表中的下一个副本节点。

HDFS安全模式_哔哩哔哩_bilibili

HDFS 安全模式 (Safe Mode) 总结

一、什么是安全模式?
  • 定义:安全模式是HDFS的一种自我保护状态。在此状态下,HDFS是只读的

  • 行为

    • 允许:读取数据请求。

    • 禁止:写入、删除、修改等所有变更命名空间的请求。

二、为什么需要安全模式?
  • 目的:为了保证集群中数据块(Block)的安全性和可靠性

  • 机制当HDFS检测到集群状态“不安全”(即可能存在数据丢失风险)时,会主动进入安全模式,冻结所有写操作,防止在状态不确定时进行修改导致更严重的问题。

三、进入/退出安全模式的条件(核心机制)

触发和退出安全模式的核心依据是数据块的上报率

  • 触发条件(进入安全模式)

    • 已上报的数据块数量 / 总数据块数量 < 阈值 时,系统自动进入安全模式。

    • 默认阈值0.999 (即 99.9%)。

    • 举例:一个集群有1000个Block。

      • 如果只有10个Block被上报,上报率为1%,远低于99.9%,触发安全模式

      • 如果有998个Block被上报,上报率为99.8%,仍低于99.9%,仍处于安全模式

  • 退出条件(离开安全模式)

    • 已上报的数据块数量 / 总数据块数量 >= 阈值 时,系统自动离开安全模式。

    • 举例:接上例,当上报的Block数从998变成999时,上报率达到99.9%,满足条件,集群自动退出安全模式,恢复正常读写功能。

四、导致安全模式的常见原因

根本原因都是导致了Block上报率的缺失或不足。

  1. NameNode重启(最常见)

    • 原因:NameNode元数据存储在内存中,重启后内存清空,Block映射关系丢失。此时上报率为0%。

    • 过程:NameNode启动后进入安全模式,等待所有DataNode通过心跳上报其存储的Block列表。随着上报的进行,上报率逐渐升高,达到阈值后自动退出。

    • 结论NameNode刚重启后处于安全模式是正常现象,需等待其自动恢复。

  2. DataNode异常

    • 原因:部分DataNode进程宕机、网络故障导致无法连接,或DataNode刚启动还未完成上报。

    • 影响:这些宕机节点上的Block无法被上报,导致总上报率下降,可能触发安全模式。

    • 排查:这是生产环境中最需要关注的原因需检查DataNode的日志和状态。

  3. NameNode本地存储问题

    • 原因:NameNode所在的服务器磁盘空间不足,导致无法正常写入或读取FsImage和Edits日志文件。

    • 影响元数据管理功能出现异常,可能无法正常处理DataNode的心跳上报,从而触发安全模式。

    • 排查:如果DataNode均正常,则应检查NameNode的磁盘空间和日志。

五、排查与处理建议

当集群意外地长时间处于安全模式时,应按照以下顺序进行排查:

  1. 首要排查DataNode

    • 使用 hdfs dfsadmin -report 命令查看所有DataNode的在线状态。

    • 检查是否有DataNode宕机或显示为异常状态。大部分情况是某个或某些DataNode挂掉导致

    • 重启异常的DataNode进程。

  2. 其次排查NameNode

    • 如果DataNode全部正常,则检查NameNode的磁盘空间,清理足够空间。

    • 查看NameNode的日志(hadoop-hdfs-namenode-<hostname>.log),寻找错误信息。

  3. (可选)手动操作

    • 确认数据块确实没有丢失(例如只是临时故障)的情况下,有时可以手动强制退出安全模式(但不推荐首选):hdfs dfsadmin -safemode leave

    • 获取安全模式状态:hdfs dfsadmin -safemode get


总结:安全模式是HDFS的“保险丝”。NameNode重启后短暂进入安全模式是正常的,只需等待其自动恢复。如果集群意外陷入安全模式,应优先检查DataNode的健康状态,这是最常见的故障点。

HDFS高可用_哔哩哔哩_bilibili

联邦机制——Federation(多台namenode)

HDFS 高可用 (High Availability) 

一、单NameNode架构的缺陷
  1. 内存上限问题:单台NameNode服务器的内存容量限制了整个HDFS集群可管理的文件数量(因为所有元数据都存在内存中)。

  2. 单点故障 (SPOF) 问题:唯一的NameNode宕机将导致整个HDFS集群不可用,无法进行任何元数据操作。


二、解决内存上限:联邦 (Federation)
  • 机制:引入多个独立的NameNode(或NameService),每个NameNode管理文件系统命名空间的一部分(例如,/user 由一个NN管理,/data 由另一个NN管理)。

  • 优点

    • 水平扩展命名空间:通过添加NameNode来扩展整个集群的元数据处理能力,突破单机内存限制。

    • 隔离性:各个NameNode管理的命名空间相互独立,互不影响。

  • 注意:联邦解决的是扩展性问题,而非可用性问题。联邦中的每个NameNode仍然是一个潜在的单点故障。


三、解决单点故障:高可用 (HA)

HA通过主备NameNode机制来解决单点故障,确保服务不间断。

  • 核心角色

    • Active NameNode:处理所有客户端请求,管理集群。

    • Standby NameNode:Active NameNode的热备节点,时刻准备接管工作。生产环境中可以配置多个。

  • 核心目标:当Active NameNode发生故障时,能自动、快速地将Standby NameNode切换为Active状态,对用户透明。


四、HA的实现:依赖两个关键组件

高可用架构需要两个外部组件协同工作来实现故障转移和数据同步。

1. JournalNodes (JN) - 共享元数据存储
  • 角色:一个由奇数台(如3、5台)节点组成的轻量级集群,用于共享存储Edits日志

  • 工作流程

    • Active NameNode将所有的元数据更改操作(Edits)同时写入(多副本) 大多数JournalNodes。

    • Standby NameNode持续地监听并从JN集群拉取最新的Edits

    • Standby NameNode在自身内存中重放这些Edits,从而使其元数据状态与Active NameNode保持近乎实时同步

  • 为什么需要JN?:确保Active和Standby NameNode的元数据状态一致。如果Edits只写在Active本地,宕机后Standby将无法获取最新日志,无法正确接管。

2. ZooKeeper (ZK) - 分布式协调与故障转移
  • 角色:一个可靠的分布式协调服务,负责监控NameNode状态主导故障转移(Failover)

  • 工作流程

    • 每个NameNode上都运行一个ZKFailoverController (ZKFC) 轻量级进程。

    • ZKFC定期通过ZK与其它节点通信,监控其所监视的NameNode的健康状态

    • 如果Active NameNode宕机(或网络分区),其对应的ZKFC与ZK的会话将过期。

    • ZK会通知Standby节点上的ZKFC。

    • ZKFC会触发一个选举过程,选出一个新的Standby节点将其提升为Active状态

  • 为什么需要ZK?:提供了一个可靠、高效、公正的“裁判”机制,来自动化完成状态监控和主备切换,避免了人工干预的延迟和错误。

五、总结:HA如何工作
  1. 数据同步:通过JournalNodes,Standby NameNode实时同步Active NameNode的元数据更改。

  2. 状态监控:通过ZooKeeperZKFC进程,持续监控所有NameNode的健康状态。

  3. 自动故障转移:当检测到Active故障时,ZooKeeper自动触发选举,将健康的Standby NameNode提升为新的Active

  4. 客户端透明客户端通过一个逻辑的命名服务(而非物理地址)来访问HDFS,故障切换后自动连接到新的Active NameNode,感知不到后端变化。


最终结论:HDFS通过 联邦 (Federation) 解决规模扩展问题,通过 高可用 (HA) 解决服务可用性问题。HA的实现依赖于 JournalNodes 保证数据一致性,以及 ZooKeeper 实现自动化的故障转移,共同构成了一个健壮的生产级HDFS集群。

HDFS基本用法_哔哩哔哩_bilibili

HDFS 操作命令

HDFS提供了多种方式来与其进行交互,主要分为Shell命令行REST API两种,分别面向运维和开发人员。

一、Shell 命令行操作 (针对运维/用户)

Shell命令是与HDFS交互最直接、最常用的方式,其语法与Linux文件操作命令高度相似,易于上手。

  1. 命令前缀

    • hadoop fs ... (通用性强,可操作多种文件系统,如HDFS, Local FS, S3等)

    • hdfs dfs ... (专用于HDFS,但与 hadoop fs 在HDFS上的功能完全一致)

    • hadoop dfs ... (已过时,不推荐使用)

    总结hadoop fs 和 hdfs dfs 可任意选用,没有功能区别。

  2. 常用操作命令
    这些命令在两种前缀下通用,其参数与Linux命令几乎一致。

    命令 功能 示例
    -ls <路径> 列出目录内容 hdfs dfs -ls /tmp
    -mkdir <路径> 创建目录 hdfs dfs -mkdir /user/hadoop
    -put <本地源> <HDFS目标> 本地文件系统上传文件/目录到HDFS hdfs dfs -put data.txt /tmp/
    -get <HDFS源> <本地目标> 从HDFS下载文件/目录到本地文件系统 hdfs dfs -get /tmp/data.txt .
    -cp <源> <目标> 在HDFS内部复制文件/目录 hdfs dfs -cp /file1 /backups/
    -mv <源> <目标> 在HDFS内部移动文件/目录 hdfs dfs -mv /olddir /newdir
    -rm [-r] <路径> 删除文件(加 -r 选项删除目录) hdfs dfs -rm /tmp/file.txt
    hdfs dfs -rm -r /tmp/logs
    -cat <文件路径> 查看HDFS上文件的内容 hdfs dfs -cat /tmp/data.txt
    -chmod-chown 修改文件权限和属主 hdfs dfs -chmod 755 /tmp/script.sh
  3. 路径格式

    • 简写格式:当你的客户端已经配置了默认的HDFS集群地址时,可以直接使用路径。这种方式操作的是默认集群。

      • 示例:hdfs dfs -ls /tmp (操作默认集群的 /tmp 目录)

    • 全写格式(标准URI):当需要明确指定操作的HDFS集群时,使用完整的URI。格式为:hdfs://<namenode_host>:<port>/<path>

      • <namenode_host>:<port>:NameNode的主机名/IP和RPC端口(默认通常是8020或9000)。

      • 何时使用:需要操作非默认的HDFS集群时;在脚本中为了清晰明确。

      • 示例:hdfs dfs -ls hdfs://namenode01:8020/tmp (明确操作namenode01集群的/tmp目录)

二、REST API 操作 (针对开发)

REST API提供了通过HTTP协议操作HDFS的方式,其最大优势是语言无关性任何能发送HTTP请求的编程语言都可以调用,极大方便了应用开发。

  1. 核心价值通用性。Java, Python, Go, JavaScript等语言都可以轻松集成HDFS操作,而不必依赖Hadoop的Java客户端。

  2. 如何调用

    • 使用HTTP方法(PUT, GET, POST, DELETE等)向特定的URL发起请求。

    • URL中需要包含HDFS集群地址和WebHDFS服务的端口(默认通常是9870)。

    • 通常需要在URL中包含参数 op= 来指定要执行的操作。

  3. 操作示例上传文件 (HTTP PUT)

curl -i -X PUT \
"http://<namenode_host>:9870/webhdfs/v1/<path>?op=CREATE&overwrite=true" \
-T <本地文件路径>

  • <namenode_host>:9870: NameNode的HTTP地址和端口。

  • /webhdfs/v1/: WebHDFS服务的固定路径。

  • op=CREATE: 操作类型为“创建”(即上传)。

  • overwrite=true: 如果文件存在则覆盖。


总结与对比
特性 Shell 命令 REST API (WebHDFS)
主要用户 系统管理员、数据工程师(运维/交互 应用程序开发者(开发集成
使用方式 在终端命令行中执行 通过HTTP客户端、代码发送HTTP请求
优势 简单直观,与Linux命令类似,易于手动操作和调试 语言无关,便于将HDFS功能集成到各种应用中
适用场景 日常的文件管理、数据探查、运维任务 开发需要访问HDFS的应用程序或服务

HDFS运维管理_哔哩哔哩_bilibili

待补充。。。


网站公告

今日签到

点亮在社区的每一天
去签到