Article
第1章 HDFS概述
1.1 分布式文件系统的基本概念
| 概念名称 | 说明 | 注意事项 |
|---|---|---|
| 分布式文件系统(Distributed File System) | 一种将数据分布存储在多台机器上的文件系统,通过网络提供统一的文件访问接口,实现数据的高可用、可扩展和容错。 | 不同于本地文件系统,分布式文件系统需处理网络延迟、节点故障等问题。 |
| 数据分片(Data Sharding/Partitioning) | 将大文件拆分为多个块(chunk/block),分布存储在不同节点上,提升并行处理能力和存储容量。 | 分片策略影响负载均衡和访问性能,需合理设计。 |
| 副本机制(Replication) | 每个数据块在多个节点上保存副本,防止因节点故障导致数据丢失,提高可靠性。 | 副本数增加可靠性但占用更多存储空间,需权衡成本与容错需求。 |
| 元数据(Metadata) | 描述文件系统结构的信息,如文件名、权限、块位置、大小等,通常由主节点集中管理。 | 元数据的高效管理是系统性能关键,NameNode即负责HDFS元数据管理。 |
| 主从架构(Master-Slave Architecture) | 由一个主节点(Master)协调多个从节点(Slave)工作,主节点负责调度和元数据管理,从节点负责数据存储。 | 主节点可能成为单点故障,HDFS HA可解决此问题。 |
1.2 HDFS的设计目标与核心思想
| 概念名称 | 说明 | 注意事项 |
|---|---|---|
| 大规模数据存储 | 支持PB级数据存储,适用于海量数据场景,如日志、视频、科学数据等。 | 设计面向大文件,不适合大量小文件存储。 |
| 流式数据访问 | 一次写入、多次读取,优化顺序读取性能,适合批处理场景。 | 不支持文件随机写入或修改,仅支持追加(append)。 |
| 高容错性 | 通过数据副本机制自动处理节点故障,保障数据不丢失。 | 默认副本数为3,可配置,但增加存储开销。 |
| 高吞吐量 | 优先保证数据吞吐率而非低延迟,适用于大数据分析任务。 | 不适合需要低延迟响应的交互式应用。 |
| 可扩展性 | 可通过增加DataNode节点横向扩展存储容量和处理能力。 | NameNode内存限制了文件数量,需考虑联邦架构应对超大规模集群。 |
1.3 HDFS的适用场景与局限性
| 场景/特性 | 说明 | 注意事项 |
|---|---|---|
| 适用场景:离线批处理 | 如MapReduce、Spark批处理作业,适合HDFS高吞吐、顺序读取特性。 | 实时流处理(如Storm、Flink)通常使用其他存储。 |
| 适用场景:大文件存储 | 存储GB到TB级大文件,如日志、备份、媒体文件。 | 小文件过多会导致NameNode内存压力大,影响性能。 |
| 适用场景:数据仓库 | Hive、Pig等工具依赖HDFS作为底层存储。 | 需配合元数据管理系统(如Metastore)使用。 |
| 局限性:低延迟访问 | HDFS设计目标非低延迟,不适合毫秒级响应需求。 | 可使用HBase、Alluxio等作为补充。 |
| 局限性:随机写入支持弱 | 不支持文件任意位置修改,仅支持追加写入。 | 需要随机写入的应用应选择其他文件系统。 |
| 局限性:小文件问题 | 每个文件、目录、块在NameNode中占用内存约150字节,过多小文件易耗尽内存。 | 可使用HAR、SequenceFile、ORC等格式合并小文件。 |
1.4 HDFS架构组件简介(NameNode、DataNode、Secondary NameNode)
| 组件名称 | 说明 | 注意事项 |
|---|---|---|
| NameNode | HDFS的主节点,管理文件系统命名空间(元数据),维护文件目录树及文件到数据块的映射,控制数据块分配与副本策略。 | 单点故障问题在非HA模式下存在,需配置HA避免宕机。 |
| DataNode | HDFS的从节点,负责实际存储数据块,执行NameNode的指令(如创建、删除、复制块)。 | 需定期向NameNode发送心跳和块报告以证明存活。 |
| Secondary NameNode | 定期合并NameNode的fsimage和edits日志,生成新的检查点,辅助NameNode进行元数据持久化。 | 并非NameNode的热备,不能自动接管服务,仅用于元数据备份与恢复。 |
第2章 HDFS核心架构与工作原理
2.1 NameNode的功能与元数据管理机制
| 概念名称 | 说明 | 注意事项 |
|---|---|---|
| 命名空间管理(Namespace) | 管理文件系统目录结构、文件权限、文件到数据块的映射关系。 | 所有操作需经过NameNode,是系统核心瓶颈之一。 |
| 元数据存储形式 | 元数据主要存储在内存中,提高访问速度;持久化通过fsimage(镜像)和edits(操作日志)文件实现。 | fsimage是完整镜像,edits记录增量修改,重启时合并恢复状态。 |
| fsimage文件 | 某一时刻HDFS元数据的完整快照,保存在磁盘上。 | 文件较大,加载时间影响NameNode启动速度。 |
| edits日志文件 | 记录自上次检查点以来所有元数据变更操作(如创建文件、删除目录等)。 | 日志不断增长,需定期合并以防过大。 |
| Checkpoint机制 | Secondary NameNode定期从NameNode获取fsimage和edits,合并生成新的fsimage并返回,减少重启恢复时间。 | 非实时同步,NameNode故障时可能丢失部分最近操作。 |
2.2 DataNode的功能与数据存储机制
| 概念名称 | 说明 | 注意事项 |
|---|---|---|
| 数据块存储 | DataNode以文件形式在本地文件系统中存储HDFS数据块,每个块对应一个文件。 | 块文件通常存储在多个磁盘路径下,提升I/O性能。 |
| 心跳机制 | DataNode每3秒向NameNode发送一次心跳,表明自身存活状态。 | 若NameNode连续10分钟未收到心跳,则判定节点失效。 |
| 块报告(Block Report) | DataNode启动时或周期性向NameNode发送其持有的所有数据块列表。 | 用于NameNode更新块位置信息,确保元数据一致性。 |
| 数据读写服务 | 接收客户端或其它DataNode的读写请求,执行数据传输。 | 支持管道式写入(pipeline write)以提高写入效率。 |
| 块扫描与校验 | 定期扫描本地块文件,验证数据完整性(如CRC校验)。 | 发现损坏块会通知NameNode并尝试从副本恢复。 |
2.3 块(Block)机制与数据分块策略
| 概念名称 | 说明 | 注意事项 |
|---|---|---|
| 数据块(Block) | HDFS中文件存储的基本单位,默认大小为128MB(Hadoop 2.x+),可配置。 | 块越大,寻址开销越小,适合大文件;块过小则增加NameNode内存压力。 |
| 分块存储 | 文件被切分为多个块,分散存储在不同DataNode上,支持并行读取。 | 最后一个块可能不满,默认也会占用一个完整块空间。 |
| 块标识(Block ID) | 每个块有唯一标识,NameNode通过ID管理块的位置与副本。 | 块ID在集群内全局唯一,用于数据定位与恢复。 |
| 块对齐与压缩 | 分块有助于与压缩格式(如Gzip、Snappy)结合,提升存储效率。 | 压缩文件若不可分割(如Gzip),则无法并行处理整个文件。 |
| 可配置块大小 | 通过dfs.blocksize参数设置,默认128MB(Hadoop 2.x及以后)。 | 应根据应用特点调整,如小文件多可适当减小块大小(但不推荐)。 |
2.4 副本机制与数据可靠性保障
| 概念名称 | 说明 | 注意事项 |
|---|---|---|
| 副本数(Replication Factor) | 每个数据块默认保存3个副本,可通过配置或上传时指定。 | 副本数越高可靠性越强,但存储成本线性增长。 |
| 副本放置策略 | 第一个副本放在上传节点(若为DataNode),第二个副本放在不同机架的节点,第三个副本放在同一机架的不同节点。 | 机架感知(Rack Awareness)需正确配置,否则影响策略效果。 |
| 副本创建与维护 | NameNode监控副本数,若发现不足(如节点宕机),会触发副本复制任务。 | 新增节点后可手动触发Balancer平衡数据。 |
| 数据恢复机制 | 当DataNode失效,NameNode检测到副本缺失,会安排其他节点复制数据补足副本数。 | 恢复速度受网络带宽和集群负载影响。 |
| 写入时的管道复制 | 客户端写入数据时,数据以管道方式依次传给多个副本节点,保证一致性。 | 若中间节点失败,管道会重建并通知客户端重试。 |
2.5 安全模式(Safe Mode)原理与作用
| 概念名称 | 说明 | 注意事项 |
|---|---|---|
| 安全模式(Safe Mode) | NameNode启动时自动进入的安全状态,在此期间不接受任何数据块的复制或删除操作。 | 是系统启动时的只读状态,用于元数据加载与验证。 |
| 进入条件 | NameNode启动时自动进入,或管理员手动触发。 | 在安全模式下,客户端可读取文件,但不能写入或删除。 |
| 退出条件 | 当满足最小副本率阈值(默认99.9%)且持续一段时间后,自动退出。 | 可通过 hdfs dfsadmin -safemode leave 强制退出。 |
| 最小副本率(Threshold) | 可通过 dfs.namenode.safemode.threshold-pct 配置,表示满足副本数的块占比。 | 若集群数据不完整(如刚恢复),可能长时间无法退出。 |
| 手动控制命令 | 支持enter、leave、get、wait等命令管理安全模式状态。 | 生产环境中谨慎使用强制退出,可能导致数据不一致。 |
2.6 Secondary NameNode的作用与检查点机制
| 概念名称 | 说明 | 注意事项 |
|---|---|---|
| 检查点(Checkpoint) | Secondary NameNode定期合并NameNode的fsimage和edits文件,生成新的fsimage,减少NameNode重启时的恢复时间。 | 并非实时备份,存在数据丢失窗口。 |
| 合并流程 | Secondary NameNode从NameNode拉取fsimage和edits → 本地合并 → 生成新fsimage → 上传回NameNode。 | 需NameNode暂停编辑日志短暂时间,影响可用性。 |
| 配置参数 | fs.checkpoint.period(检查点间隔,默认3600秒);fs.checkpoint.size(edits文件大小阈值,达到即触发)。 | 可根据集群写入频率调整,避免edits过大。 |
| 非高可用组件 | Secondary NameNode不能替代NameNode提供服务,NameNode故障时无法接管。 | 要实现高可用,必须使用HDFS HA(基于ZooKeeper和JournalNode)。 |
| 存储位置 | 合并后的fsimage和edits保存在Secondary NameNode本地磁盘,作为备份。 | 应确保其存储路径有足够的磁盘空间。 |
第3章 HDFS基本操作与命令行接口
3.1 HDFS命令行基本语法结构
| 命令格式 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 基本调用格式 | hdfs dfs [选项] [命令] [参数] | 执行HDFS文件系统操作,是最常用的命令前缀 | hdfs dfs -ls / | hdfs dfs 等价于 hadoop fs,推荐使用前者 |
| 通用选项 -D | -D <property=value> | 临时设置Hadoop配置属性 | hdfs dfs -D dfs.replication=2 -put local.txt /dest/ | 仅对当前命令生效,优先级高于配置文件 |
| 安全模式操作 | hdfs dfsadmin -safemode <enter|leave|get|wait> | 管理NameNode安全模式状态 | hdfs dfsadmin -safemode get | 需NameNode权限,通常由管理员使用 |
| 查看帮助 | hdfs dfs -help 或 hdfs dfs -help <命令> | 显示所有命令或指定命令的使用说明 | hdfs dfs -help ls | 可快速查看命令参数格式 |
3.2 文件与目录操作(创建、删除、查看等)
| 命令 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 列出文件 | hdfs dfs -ls <路径> | 显示指定路径下的文件和目录信息。 | hdfs dfs -ls /user/hadoop | 支持通配符,如 /data/*.log。 |
| 递归列出 | hdfs dfs -ls -R <路径> | 递归列出所有子目录内容。 | hdfs dfs -ls -R /data | 输出量大,谨慎使用。 |
| 创建目录 | hdfs dfs -mkdir [-p] <路径> | 创建目录,-p 表示递归创建父目录。 | hdfs dfs -mkdir -p /a/b/c | 若目录已存在,默认报错,-p 可避免。 |
| 删除文件/目录 | hdfs dfs -rm [-r] <路径> | 删除文件,-r 用于删除非空目录。 | hdfs dfs -rm -r /tmp/data | 删除操作立即生效,不进回收站(除非启用Trash)。 |
| 移动/重命名 | hdfs dfs -mv <源路径> <目标路径> | 移动或重命名文件/目录。 | hdfs dfs -mv /oldname /newname | 跨目录移动即为重命名。 |
| 显示文件头 | hdfs dfs -head <文件> | 显示文件前1KB内容。 | hdfs dfs -head /data/log.txt | 类似Linux的head命令。 |
| 显示文件尾 | hdfs dfs -tail <文件> | 显示文件最后1KB内容,支持 -f 实时追加。 | hdfs dfs -tail -f /logs/app.log | 用于查看日志输出。 |
3.3 文件上传、下载与复制操作
| 命令 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 上传文件 | hdfs dfs -put <本地路径> <HDFS路径> | 将本地文件上传到HDFS。 | hdfs dfs -put local.txt /input/ | 若目标已存在且非目录,会报错。 |
| 上传并删除源 | hdfs dfs -moveFromLocal <本地路径> <HDFS路径> | 上传后删除本地文件。 | hdfs dfs -moveFromLocal data.csv /upload/ | 类似mv语义。 |
| 下载文件 | hdfs dfs -get <HDFS路径> <本地路径> | 将HDFS文件下载到本地。 | hdfs dfs -get /output/result.txt ./ | 若本地路径已存在,会覆盖。 |
| 下载并删除源 | hdfs dfs -getmerge <HDFS路径> <本地路径> | 合并HDFS目录中所有文件并下载。 | hdfs dfs -getmerge /output/part-* all.txt | 常用于合并MapReduce输出文件。 |
| 复制文件 | hdfs dfs -cp <源> <目标> | 在HDFS内部复制文件或目录。 | hdfs dfs -cp /src/data /backup/ | 不改变源文件,支持跨目录复制。 |
| 显示文件内容 | hdfs dfs -cat <文件> | 输出文件内容到标准输出。 | hdfs dfs -cat /data/info.txt | 大文件慎用,避免输出过多。 |
| 统计文件大小 | hdfs dfs -du [-h] <路径> | 显示文件/目录大小,-h 表示易读格式。 | hdfs dfs -du -h /user/ | -du -s 可汇总总大小。 |
3.4 权限管理与所有权设置
| 命令 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 修改权限 | hdfs dfs -chmod [-R] <权限> <路径> | 修改文件/目录权限,支持符号或数字模式。 | hdfs dfs -chmod 755 /app | -R 表示递归修改子项。 |
| 修改所有者 | hdfs dfs -chown [-R] [用户:组] <路径> | 修改文件/目录的所有者和组。 | hdfs dfs -chown hadoop:hadoop /data | 需有管理员权限或文件所有者身份。 |
| 修改组 | hdfs dfs -chgrp [-R] <组> <路径> | 修改文件/目录的所属组。 | hdfs dfs -chgrp analysts /reports | 等价于 -chown :analysts。 |
| 启用回收站 | hdfs dfs -rm [-skipTrash] <路径> | 删除文件时进入回收站(默认启用)。 | hdfs dfs -rm /tmp/old | 使用 -skipTrash 可跳过回收站直接删除。 |
| 查看回收站 | hdfs dfs -ls ~/.Trash/ | 查看用户回收站中的文件。 | hdfs dfs -ls /user/hadoop/.Trash/Current/ | 回收站路径可配置,过期后自动清理。 |
3.5 文件系统状态查询与空间管理
| 命令 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 查看磁盘使用 | hdfs dfs -df [-h] <路径> | 显示HDFS文件系统的磁盘使用情况。 | hdfs dfs -df -h / | 类似Linux的df命令。 |
| 统计文件数量与大小 | hdfs dfs -count <路径> | 统计路径下的目录数、文件数和总大小。 | hdfs dfs -count /data | 输出三列:dirs, files, size。 |
| 报告集群状态 | hdfs dfsadmin -report | 显示所有DataNode的状态、容量、块数等。 | hdfs dfsadmin -report | 用于运维监控和故障排查。 |
| 进入/退出安全模式 | hdfs dfsadmin -safemode enter/leave | 手动控制NameNode安全模式。 | hdfs dfsadmin -safemode leave | 重启后自动进入,通常无需手动干预。 |
| 检查文件健康 | hdfs fsck <路径> [选项] | 检查文件系统健康状况,如缺失块、损坏块等。 | hdfs fsck / -files -blocks | hdfs fsck / -delete 可删除损坏文件。 |
| 平衡数据 | hdfs balancer [-threshold <百分比>] | 均衡各DataNode的数据分布。 | hdfs balancer -threshold 5 | 建议在网络低峰期执行,避免影响业务。 |
第4章 HDFS Java API 编程基础
4.1 配置Hadoop环境与依赖引入
| 概念 | 说明 | 注意事项 |
|---|---|---|
| Maven依赖 | 在pom.xml中引入hadoop-client依赖。 | 需确保版本与集群一致,避免兼容性问题。 |
| 示例依赖配置 | 见下方代码示例① | 版本号根据实际Hadoop版本调整。 |
| 环境变量 | 确保HADOOP_CONF_DIR或HADOOP_HOME设置正确。 | 用于加载core-site.xml、hdfs-site.xml等配置。 |
| Windows支持 | 若在Windows开发,需下载winutils.exe并配置HADOOP_HOME。 | 否则会报 java.io.IOException: Could not locate executable null\bin\winutils.exe 错误。 |
代码示例①:Maven依赖配置
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>3.3.4</version>
</dependency>
4.2 创建FileSystem实例与连接配置
| 方法 | 语法 | 用途 | 注意事项 |
|---|---|---|---|
| 获取默认FileSystem | FileSystem.get(Configuration conf) | 根据配置获取HDFS连接实例。 | fs.defaultFS 指向NameNode地址。 |
| 指定用户获取实例 | FileSystem.get(URI uri, Configuration conf, String user) | 以指定用户身份连接HDFS,用于权限控制。 | 需Kerberos或Simple认证支持。 |
| 关闭FileSystem | fs.close() | 释放连接资源。 | 必须显式关闭,避免资源泄漏。 |
| 判断文件系统类型 | fs instanceof DistributedFileSystem | 判断是否为HDFS实例。 | 用于条件逻辑处理。 |
代码示例②:获取FileSystem连接
Configuration conf = new Configuration();
conf.set("fs.defaultFS", "hdfs://namenode:9000");
FileSystem fs = FileSystem.get(conf);
代码示例③:以指定用户获取实例
FileSystem fs = FileSystem.get(URI.create("hdfs://nn:9000"), conf, "hadoop");
代码示例④:关闭FileSystem
try (FileSystem fs = FileSystem.get(conf);
FSDataOutputStream out = fs.create(p)) {
out.write(data);
}
4.3 文件的创建、写入与关闭
| 方法 | 语法 | 用途 | 注意事项 |
|---|---|---|---|
| 创建并写入文件 | fs.create(Path path) | 创建新文件并返回FSDataOutputStream。 | 若文件已存在,默认抛FileAlreadyExistsException。 |
| 设置副本数 | fs.create(Path path, short replication) | 指定写入文件的副本数量。 | 默认使用 dfs.replication 配置值。 |
| 设置块大小 | fs.create(Path path, long blockSize) | 指定文件块大小。 | 单位为字节。 |
| 追加写入 | fs.append(Path path) | 向已有文件末尾追加数据。 | 文件必须存在且支持追加(需配置 dfs.support.append=true)。 |
| 强制刷新 | out.hsync() 或 out.hflush() | 确保数据写入磁盘或管道所有节点。 | hsync() 更严格,保证持久化。 |
代码示例⑥:创建并写入文件
FSDataOutputStream out = fs.create(new Path("/data.txt"));
out.write("Hello HDFS".getBytes());
out.close();
代码示例⑦:设置副本数
FSDataOutputStream out = fs.create(new Path("/rep2.txt"), (short) 2);
代码示例⑧:设置块大小
FSDataOutputStream out = fs.create(new Path("/large.txt"), 256 * 1024 * 1024);
代码示例⑨:追加写入
FSDataOutputStream out = fs.append(new Path("/log.txt"));
代码示例⑩:强制刷新
out.write(data);
out.hsync();
4.4 文件的读取与数据输出
| 方法 | 语法 | 用途 | 注意事项 |
|---|---|---|---|
| 打开文件 | fs.open(Path path) | 打开文件并返回FSDataInputStream。 | 支持随机读取。 |
| 指定读取位置 | in.seek(long position) | 移动读取指针到指定偏移量。 | 用于实现断点续读或索引访问。 |
| 跳过字节 | in.skip(long n) | 跳过指定数量的字节。 | 不保证完全跳过n字节,应检查返回值。 |
| 读取全部内容 | IOUtils.copyBytes(in, System.out, 4096, false) | 使用Hadoop工具类流式输出。 | 第四个参数为 true 时会自动关闭流。 |
| 缓冲读取 | 包装BufferedInputStream | 提升小数据读取性能。 | 减少I/O调用次数。 |
代码示例⑪:打开文件并读取
FSDataInputStream in = fs.open(new Path("/data.txt"));
byte[] buf = new byte[1024];
in.read(buf);
in.close();
代码示例⑫:指定读取位置
in.seek(100); // 从第100字节开始读
代码示例⑬:跳过字节
in.skip(50);
代码示例⑭:读取全部内容
FSDataInputStream in = fs.open(p);
IOUtils.copyBytes(in, System.out, 4096, false);
代码示例⑮:缓冲读取
BufferedInputStream bis = new BufferedInputStream(fs.open(p));
4.5 目录与文件的元信息操作
| 方法 | 语法 | 用途 | 注意事项 |
|---|---|---|---|
| 获取文件状态 | fs.getFileStatus(Path path) | 获取文件或目录的详细信息(大小、权限、块大小等)。 | 若路径不存在,抛FileNotFoundException。 |
| 列出文件状态 | fs.listStatus(Path path) | 返回目录下所有文件/子目录的状态数组。 | 不递归,仅当前层级。 |
| 递归列出 | fs.listFiles(Path path, boolean recursive) | 递归列出所有文件及其块信息。 | 返回迭代器,适合大数据量。 |
| 判断路径是否存在 | fs.exists(Path path) | 检查文件或目录是否存在。 | 最常用的状态检查方法。 |
| 判断是否为目录 | status.isDirectory() | 根据FileStatus判断类型。 | 需先调用getFileStatus。 |
| 获取文件块位置 | fs.getFileBlockLocations(Path path, long offset, long len) | 获取指定范围数据块的物理位置(主机名)。 | 用于实现数据本地性优化。 |
代码示例⑯:获取文件状态
FileStatus status = fs.getFileStatus(new Path("/data"));
System.out.println(status.getLen());
代码示例⑰:列出文件状态
FileStatus[] statuses = fs.listStatus(new Path("/dir"));
代码示例⑱:递归列出
RemoteIterator<LocatedFileStatus> it = fs.listFiles(new Path("/data"), true);
代码示例⑲:判断路径是否存在
if (fs.exists(p)) { ... }
代码示例⑳:判断是否为目录
if (status.isDirectory()) { ... }
代码示例㉑:获取文件块位置
BlockLocation[] blocks = fs.getFileBlockLocations(p, 0, status.getLen());
4.6 文件的删除、重命名与移动
| 方法 | 语法 | 用途 | 注意事项 |
|---|---|---|---|
| 删除文件/目录 | fs.delete(Path path, boolean recursive) | 删除文件或目录,recursive=true时删除非空目录。 | 返回boolean表示是否删除成功。 |
| 重命名/移动 | fs.rename(Path src, Path dst) | 重命名或移动文件/目录。 | 跨文件系统不支持;目标路径不能已存在。 |
| 检查删除结果 | 返回值判断 | delete() 方法返回布尔值,表示操作是否成功。 | 应检查返回值进行错误处理。 |
代码示例㉒:删除文件/目录
boolean result = fs.delete(new Path("/tmp"), true);
代码示例㉓:重命名/移动
boolean success = fs.rename(p1, p2);
代码示例㉔:检查删除结果
if (!fs.delete(p, true)) { throw new IOException("Delete failed"); }
4.7 权限与ACL的API操作
| 方法 | 语法 | 用途 | 注意事项 |
|---|---|---|---|
| 修改权限 | fs.setPermission(Path path, FsPermission permission) | 设置文件/目录的权限(如755)。 | 需有文件所有者或管理员权限。 |
| 修改所有者 | fs.setOwner(Path path, String username, String groupname) | 修改文件/目录的所有者和组。 | 用户和组必须存在。 |
| 设置ACL | fs.setAcl(Path path, List<AclEntry> aclSpec) | 设置访问控制列表(ACL),提供更细粒度权限。 | 需HDFS启用ACL支持(dfs.namenode.acls.enabled=true)。 |
| 获取ACL | fs.getAclStatus(Path path) | 获取路径的ACL状态信息。 | 包含访问ACL和默认ACL。 |
代码示例㉕:修改权限
fs.setPermission(p, new FsPermission((short) 0755));
代码示例㉖:修改所有者
fs.setOwner(p, "hadoop", "users");
代码示例㉗:设置ACL
List<AclEntry> acl = Arrays.asList(
new AclEntry.Builder()
.setName("dev")
.setPermission(FsAction.READ)
.setScope(AclEntryScope.ACCESS)
.setType(AclEntryType.USER)
.build()
);
fs.setAcl(p, acl);
代码示例㉘:获取ACL
AclStatus status = fs.getAclStatus(p);
4.8 异常处理与资源管理
| 异常类型 | 说明 | 处理建议 | 注意事项 |
|---|---|---|---|
| IOException | 所有HDFS I/O操作可能抛出的基类异常。 | 使用try-catch捕获,并记录日志。 | 应作为顶层捕获异常。 |
| FileNotFoundException | 访问的路径不存在。 | 检查路径拼写或前置创建逻辑。 | 常见于 open() 或 getFileStatus()。 |
| FileAlreadyExistsException | 创建文件时目标已存在。 | 使用 delete() 先删除,或改用追加模式。 | create() 默认不覆盖。 |
| UnresolvedLinkException | 路径包含符号链接无法解析。 | 检查HDFS符号链接配置与权限。 | 较少见。 |
| 资源未关闭 | FileSystem、FSDataInputStream、FSDataOutputStream未关闭导致连接泄漏。 | 使用try-with-resources或finally块确保关闭。 | 建议使用try-with-resources语法。 |
代码示例㉙:try-with-resources资源管理
try (FileSystem fs = FileSystem.get(conf);
FSDataOutputStream out = fs.create(p)) {
out.write(data);
}
第5章 HDFS高级特性与优化
5.1 HDFS快照(Snapshot)功能与使用
| 方法/命令 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 创建快照 | hdfs dfsadmin -createSnapshot <目录路径> [快照名] | 在指定目录创建快照,用于数据备份或回滚。 | hdfs dfsadmin -createSnapshot /data snap1 | 源目录必须启用快照功能。 |
| 删除快照 | hdfs dfsadmin -deleteSnapshot <目录路径> <快照名> | 删除指定名称的快照。 | hdfs dfsadmin -deleteSnapshot /data snap1 | 快照删除不可逆,请谨慎操作。 |
| 重命名快照 | hdfs dfsadmin -renameSnapshot <目录路径> <旧名> <新名> | 修改快照名称。 | hdfs dfsadmin -renameSnapshot /data snap1 snap2 | 便于管理和识别。 |
| 启用快照功能 | hdfs dfsadmin -allowSnapshot <目录路径> | 允许该目录创建快照。 | hdfs dfsadmin -allowSnapshot /data | 默认禁用,需手动开启。 |
| 禁用快照功能 | hdfs dfsadmin -disallowSnapshot <目录路径> | 禁止该目录使用快照,删除所有现有快照。 | hdfs dfsadmin -disallowSnapshot /data | 执行后无法恢复快照。 |
| 列出快照 | hdfs ls /<目录>/.snapshot/ | 查看指定目录下的所有快照。 | hdfs dfs -ls /data/.snapshot/snap1 | 快照存储在隐藏目录 .snapshot 中。 |
| 差异比较 | hdfs snapshotDiff <目录> <快照1> <快照2> | 显示两个快照之间的文件差异(新增、修改、删除)。 | hdfs snapshotDiff /data snap1 snap2 | 用于审计或恢复特定变更。 |
5.2 透明加密(HDFS Encryption Zone)
| 方法/命令 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 创建密钥 | hadoop key create <密钥名> | 在KMS中创建加密密钥。 | hadoop key create mykey | 需配置Key Management Server (KMS)。 |
| 创建加密区 | hdfs crypto -createZone -keyName <密钥名> -path <目录> | 将指定目录设为加密区,其内文件自动加密存储。 | hdfs crypto -createZone -keyName mykey -path /secure | 目录必须为空,且由超级用户操作。 |
| 列出加密区 | hdfs crypto -listZones | 查看集群中所有加密区及其密钥。 | hdfs crypto -listZones | 用于审计和管理。 |
| 获取加密区信息 | hdfs getconf -encryptionZones | 显示加密区配置信息。 | hdfs getconf -encryptionZones | 另一种查看方式。 |
| 解密文件读取 | hdfs dfs -cat /secure/secret.txt | 用户读取加密区文件时自动解密,无需感知。 | hdfs dfs -cat /secure/data.enc | 透明性体现:应用无需修改。 |
| 密钥轮换 | hadoop key rollOver <密钥名> | 密钥轮换,提升安全性。 | hadoop key rollOver mykey | 密钥管理需严格遵循安全策略。 |
| 删除密钥 | hadoop key delete <密钥名> | 删除指定密钥。 | hadoop key delete mykey | 密钥管理需严格遵循安全策略。 |
5.3 HDFS配额管理(Quota)
| 方法/命令 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 设置名称配额 | hdfs dfsadmin -setQuota <数量> <目录> | 限制目录下最多可创建的文件和目录总数。 | hdfs dfsadmin -setQuota 1000 /user/test | 超过配额将拒绝创建新文件。 |
| 取消名称配额 | hdfs dfsadmin -clrQuota <目录> | 清除名称配额限制。 | hdfs dfsadmin -clrQuota /user/test | 恢复无限创建能力。 |
| 设置空间配额 | hdfs dfsadmin -setSpaceQuota <大小> <目录> | 限制目录下文件总大小(单位:字节,支持k,m,g,t)。 | hdfs dfsadmin -setSpaceQuota 10g /user/test | 包括所有副本占用空间。 |
| 取消空间配额 | hdfs dfsadmin -clrSpaceQuota <目录> | 清除空间配额限制。 | hdfs dfsadmin -clrSpaceQuota /user/test | 恢复无限存储能力。 |
| 查看配额与使用 | hdfs dfs -count -q <目录> | 显示目录的配额设置及当前使用情况。 | hdfs dfs -count -q /user/test | 输出包括:名称配额、已用、空间配额、已用。 |
5.4 HDFS高可用(HA)架构原理
| 概念名称 | 说明 | 注意事项 |
|---|---|---|
| NameNode HA(High Availability) | 通过部署两个NameNode(Active + Standby)避免单点故障,使用共享存储(如QJM或NFS)同步元数据。 | 必须配置ZooKeeper实现故障自动切换(Failover)。 |
| JournalNode 集群(QJM) | 用于共享edits日志的节点组,Active NN写入edits,Standby NN读取并同步状态。 | 建议部署奇数个(如3或5),保证多数派写入成功。 |
| ZooKeeper Failover Controller(ZKFC) | 每个NameNode节点运行ZKFC进程,监控NN健康状态,并在故障时通过ZooKeeper触发自动切换。 | ZKFC负责选举Active节点。 |
| 故障切换(Failover) | 当Active NN宕机,ZKFC检测到后,ZooKeeper协调将Standby NN提升为Active,对外提供服务。 | 切换时间通常在几十秒内,对客户端透明。 |
| 客户端自动重定向 | 客户端通过逻辑URI(如 hdfs://mycluster)访问,配置文件中映射到多个NN地址,自动重试。 | 需配置 hdfs-site.xml 中的 dfs.nameservices 等参数。 |
5.5 HDFS联邦(Federation)机制
| 概念名称 | 说明 | 注意事项 |
|---|---|---|
| HDFS Federation(联邦) | 允许一个HDFS集群中存在多个独立的命名空间(由多个NameNode管理),共享底层DataNode存储资源。 | 解决单NameNode内存瓶颈和扩展性问题。 |
| 命名空间ID(Namespace ID) | 每个NameNode有唯一命名空间ID,管理自己的元数据。 | 不同NN之间元数据不共享。 |
| Block Pool(块池) | 每个命名空间对应一个块池,DataNode为每个块池存储其数据块。 | DataNode上存储多个块池的数据。 |
| Router(可选) | 使用HDFS Router(如ViewFS)实现路径挂载,将不同命名空间映射到统一视图。 | 客户端通过ViewFS访问 /ns1, /ns2 等路径。 |
| 配置方式 | 配置多个 dfs.nameservices,每个对应一个NameNode组。 | 复杂度高,适用于超大规模集群(PB级以上)。 |
5.6 小文件问题与合并策略
| 问题/策略 | 说明 | 注意事项 |
|---|---|---|
| 小文件问题根源 | 每个文件、目录、块在NameNode内存中占用约150字节,大量小文件导致内存耗尽,影响性能。 | 典型场景:日志采集、传感器数据。 |
| HAR文件(Hadoop Archive) | 将多个小文件打包成HAR归档文件,减少NameNode内存压力,但仍可访问。 | 访问路径为 /output/logs.har#logs/file1。 |
| SequenceFile | 使用二进制键值对格式存储多个小文件,键为文件名,值为内容。 | 适合MapReduce处理,但不支持随机访问。 |
| Avro / ORC / Parquet | 使用列式存储格式合并小文件,提升查询效率和压缩比。 | 常用于数据湖场景,如Hive表存储。 |
| HBase | 将小文件数据存入HBase,利用其LSM树结构高效管理海量小对象。 | 适合需要随机读写的场景。 |
| 中间聚合 | 在数据采集阶段增加聚合逻辑(如Flume Channel、Kafka + Spark Streaming),批量写入HDFS。 | 从源头减少小文件产生。 |
代码示例①:创建HAR归档文件
hadoop archive -archiveName logs.har -p /input logs /output
5.7 数据均衡与Balancer工具
| 方法/命令 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 启动Balancer | hdfs balancer [-threshold <百分比>] | 平衡DataNode之间的数据分布,避免磁盘使用不均。 | hdfs balancer -threshold 5 | 默认阈值10%,建议设置为5%~10%。 |
| 指定带宽限制 | -D dfs.datanode.balance.bandwidthPerSec=<字节数> | 限制Balancer使用的网络带宽,避免影响业务。 | hdfs balancer -threshold 5 -D dfs.datanode.balance.bandwidthPerSec=10485760 | 单位为字节/秒,例如10MB/s。 |
| 指定均衡策略 | hdfs balancer -policy <datanode|blockpool> | datanode(默认)按节点均衡;blockpool 按块池均衡(联邦场景)。 | hdfs balancer -policy datanode | 多数情况使用默认策略。 |
| 查看Balancer日志 | 日志文件 hadoop-hdfs-balancer-*.log | 查看均衡进度、传输速率、剩余时间等。 | tail -f /logs/hadoop-hdfs-balancer-hadoop.log | Balancer运行在客户端节点。 |
| 自动均衡脚本 | 结合crontab定期执行Balancer | 实现自动化运维。 | 0 2 * * * /usr/local/hadoop/bin/hdfs balancer -threshold 5 >> /var/log/hdfs-balance.log 2>&1 | 建议在业务低峰期执行。 |
第6章 HDFS运维与监控
6.1 日常运维命令与健康检查
| 命令 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 检查集群状态 | hdfs dfsadmin -report | 查看所有DataNode的健康状态、容量、块数、版本等。 | hdfs dfsadmin -report | 运维必用命令,检查节点是否丢失。 |
| 检查文件系统完整性 | hdfs fsck <路径> [选项] | 检测文件块缺失、损坏、过度复制等问题。 | hdfs fsck / -files -blocks -locations | hdfs fsck / -delete 可清理损坏文件。 |
| 查看安全模式 | hdfs dfsadmin -safemode get | 检查NameNode是否处于安全模式。 | hdfs dfsadmin -safemode get | 启动后通常自动退出。 |
| 强制退出安全模式 | hdfs dfsadmin -safemode leave | 手动退出安全模式(谨慎使用)。 | hdfs dfsadmin -safemode leave | 确保元数据加载完成后再执行。 |
| 查看配置 | hdfs getconf -confKey <配置项> | 查看运行时配置值。 | hdfs getconf -confKey fs.defaultFS | 验证配置是否生效。 |
| 刷新节点 | hdfs dfsadmin -refreshNodes | 重新加载exclude/include文件,实现节点下线或上线。 | hdfs dfsadmin -refreshNodes | 配合 dfs.hosts.exclude 使用。 |
6.2 日志分析与故障排查
| 日志类型 | 存储路径 | 常见问题 | 分析方法 | 注意事项 |
|---|---|---|---|---|
| NameNode日志 | ${HADOOP_LOG_DIR}/hadoop-<user>-namenode-<host>.log | 启动失败、安全模式无法退出、元数据加载异常。 | 搜索ERROR, FATAL, Exception关键字;关注Edits加载、FSImage解析过程。 | 日志量大,建议使用grep, less, tail -f。 |
| DataNode日志 | ${HADOOP_LOG_DIR}/hadoop-<user>-datanode-<host>.log | 心跳丢失、块报告失败、磁盘故障、权限错误。 | 检查BlockReport, Heartbeat, DiskErrorException等关键词。 | 磁盘满或损坏是常见原因。 |
| Secondary NameNode日志 | ${HADOOP_LOG_DIR}/hadoop-<user>-secondarynamenode-<host>.log | 检查点失败、无法连接NameNode。 | 检查Checkpoint流程日志,确认fsimage和edits拉取是否成功。 | 网络或权限问题可能导致失败。 |
| GC日志 | 配置 -Xloggc:<path> | NameNode内存不足、Full GC频繁、长时间停顿。 | 使用GCViewer, gceasy.io分析GC频率、停顿时长、内存使用趋势。 | NameNode堆内存通常配置较大(如32GB+)。 |
| JMX监控 | jconsole, jvisualvm, 或Prometheus+JMX Exporter | 内存泄漏、线程阻塞、RPC队列积压。 | 监控HeapMemoryUsage, Threads, RpcQueueTime等指标。 | 实时诊断性能瓶颈。 |
6.3 NameNode元数据备份与恢复
| 操作 | 方法 | 用途 | 注意事项 |
|---|---|---|---|
| 手动备份fsimage和edits | 从NameNode节点复制 $dfs.namenode.name.dir 和 $dfs.namenode.edits.dir 目录下的文件。 | 定期归档元数据,防止意外丢失。 | 建议结合 hdfs dfsadmin -saveNamespace 强制生成新fsimage。 |
| 强制保存命名空间 | hdfs dfsadmin -saveNamespace | 将当前内存状态保存为新的fsimage,清空edits日志。 | 只能在Active NameNode上执行,且不在安全模式。 |
| 从Checkpoint恢复 | 将Secondary NameNode的 $dfs.namenode.checkpoint.dir 中的最新fsimage和edits复制到NameNode元数据目录。 | NameNode元数据损坏时的恢复手段。 | 需停止HDFS服务,替换目录后重启。 |
| 配置远程备份 | 使用脚本定期将元数据目录同步到远程服务器(如rsync, scp)。 | 防止本地磁盘故障导致元数据丢失。 | 建议加密传输和存储。 |
恢复步骤:
- 停止HDFS
- 备份原元数据目录
- 替换为备份的fsimage和edits
- 启动NameNode
注意:恢复后可能丢失最近未持久化的操作。
6.4 HDFS性能监控指标
| 指标类别 | 关键指标 | 正常范围/关注点 | 监控工具 | 注意事项 |
|---|---|---|---|---|
| NameNode | Heap Usage, GC Time, RPC Queue Time, Files Total, Pending Replication Blocks | Heap使用率<80%;GC暂停<1s;RPC队列长度稳定。 | Ganglia, Prometheus+JMX Exporter, Ambari | NameNode是性能瓶颈,需重点监控。 |
| DataNode | Disk Usage, Block Reports, Heartbeat Latency, Read/Write Rate | 磁盘使用均衡;心跳间隔稳定(3s);无频繁超时。 | 同上 | 磁盘满或网络问题会导致节点失效。 |
| 文件系统 | Total Capacity, Used Space, Blocks Total, Missing Blocks | Missing Blocks = 0;Used Space增长平稳。 | HDFS Web UI (http://namenode:9870) | Missing Blocks > 0 表示数据丢失风险。 |
| 网络 | Balancer Traffic, Client I/O Throughput | Balancer带宽不影响业务;客户端读写速率稳定。 | nload, iftop, Hadoop Metrics | 避免Balancer占用过多带宽。 |
| 用户行为 | Active Clients, Read/Write Requests, File Open Rate | 无异常突增,符合业务规律。 | 自定义监控脚本或平台 | 防止恶意扫描或程序bug导致负载过高。 |
6.5 常见问题与解决方案
| 问题现象 | 可能原因 | 解决方案 | 注意事项 |
|---|---|---|---|
| NameNode无法启动 | 元数据损坏、磁盘满、端口占用、配置错误。 | 检查日志;尝试从Secondary NN恢复;清理磁盘;检查 hdfs-site.xml。 | 启动前确保 $dfs.namenode.name.dir 可写。 |
| DataNode无法注册 | 主机名解析失败、防火墙阻止、版本不匹配、配置slaves文件错误。 | 检查 /etc/hosts 或DNS;关闭防火墙;确认Hadoop版本一致;检查workers文件。 | Hadoop 3.x 使用workers而非slaves。 |
| 安全模式长时间不退出 | 副本率低于阈值(如99.9%),存在缺失块。 | 执行 hdfs fsck / 检查缺失块;等待副本复制完成;或临时降低阈值(dfs.namenode.safemode.threshold-pct=0.9)。 | 生产环境避免强制 -leave,可能导致数据不一致。 |
| 写入速度慢 | 网络带宽不足、磁盘I/O瓶颈、副本数过多、客户端资源不足。 | 减少副本数测试;检查网络和磁盘负载;优化客户端代码(如增大缓冲区)。 | 使用 hdfs dfs -put 测试基准性能。 |
| 小文件导致NameNode内存溢出 | 文件数量过多,超出NameNode内存容量。 | 合并小文件(HAR, SequenceFile);启用联邦;增加NameNode堆内存。 | 长期方案是优化数据采集流程。 |
| Balancer无法完成 | 带宽限制过低、集群负载高、节点磁盘使用差异大。 | 提高bandwidthPerSec;在低峰期运行;分批均衡。 | Balancer不保证完全均衡,达到阈值即停止。 |
第7章 HDFS与其他生态系统集成
7.1 HDFS与MapReduce的集成
| 方法/机制 | 语法/说明 | 用途 | 注意事项 |
|---|---|---|---|
| InputFormat读取HDFS文件 | FileInputFormat.setInputPaths(job, new Path("hdfs://...")); | MapReduce作业从HDFS读取输入数据,按块切分输入分片(InputSplit)。 | 默认按HDFS块大小切分,确保数据本地性。 |
| OutputFormat写入HDFS | FileOutputFormat.setOutputPath(job, new Path("hdfs://...")); | 将MapReduce输出结果写入HDFS指定目录。 | 输出目录不能预先存在,否则作业失败。 |
| 数据本地性优化 | HDFS块位置信息传递给YARN | 调度器优先将Map任务分配到存储对应数据块的DataNode上执行。 | 提升性能,减少网络传输开销。 |
| SequenceFile作为中间格式 | SequenceFileOutputFormat | 在MapReduce之间传递结构化数据,支持压缩和高效序列化。 | 适用于多Job串联场景。 |
| 小文件合并输入 | CombineTextInputFormat | 将多个小文件合并为一个InputSplit,减少Map任务数。 | 避免过多小任务导致调度开销。 |
代码示例②:InputFormat读取HDFS文件
job.setInputFormatClass(TextInputFormat.class);
FileInputFormat.addInputPath(job, new Path("/input/data.txt"));
代码示例③:OutputFormat写入HDFS
FileOutputFormat.setOutputPath(job, new Path("/output/result"));
代码示例④:SequenceFile作为中间格式
job.setOutputFormatClass(SequenceFileOutputFormat.class);
代码示例⑤:小文件合并输入
job.setInputFormatClass(CombineTextInputFormat.class);
7.2 HDFS与YARN的协作机制
| 机制 | 说明 | 用途 | 注意事项 |
|---|---|---|---|
| 资源存储路径配置 | yarn.nodemanager.local-dirs / yarn.nodemanager.log-dirs | NodeManager在本地磁盘存储容器临时文件和日志,但最终日志可汇聚到HDFS。 | 配置为多块磁盘路径以提升I/O性能。 |
| 容器日志聚合 | yarn.log-aggregation-enable=true / yarn.nodemanager.remote-app-log-dir=/var/log | 将各节点上的应用日志上传并集中存储在HDFS中,便于统一查看。 | 日志保留时间由 yarn.log-retention-seconds 控制,默认10天。 |
| Application History Server | mapreduce.jobhistory.address / mapreduce.jobhistory.webapp.address | 从HDFS读取作业历史日志并提供Web查询接口。 | 历史日志写入HDFS路径如 /mr-history/done。 |
| 共享基础服务 | HDFS作为YARN的底层文件系统 | YARN的各类服务(如Timeline Server、Custom Log Handlers)可将数据持久化到HDFS。 | 所有分布式组件依赖HDFS实现高可用存储。 |
7.3 HDFS与Hive的数据存储交互
| 机制/命令 | 语法 | 用途 | 注意事项 |
|---|---|---|---|
| 表数据存储路径 | LOCATION 'hdfs://...' | 指定Hive表或分区的数据在HDFS上的存储位置。 | 若不指定,使用默认仓库路径 hive.metastore.warehouse.dir(默认 /user/hive/warehouse)。 |
| 内部表(Managed Table) | 无 LOCATION 子句 | Hive管理表的生命周期,删除表时自动删除HDFS数据。 | 适合ETL中间结果,数据完全由Hive控制。 |
| 外部表(External Table) | EXTERNAL 关键字 | 表元数据由Hive管理,但数据由外部维护,删除表仅删除元数据。 | 适合共享数据源,防止误删。 |
| 分区表存储结构 | 分区字段作为子目录 | 自动按分区字段组织HDFS目录结构,提升查询效率。 | 支持动态分区,需配置 hive.exec.dynamic.partition=true。 |
| 文件格式支持 | STORED AS ORC/Parquet/Avro | 指定HDFS中存储的文件格式,影响压缩率和查询性能。 | 列式存储(如Parquet)适合OLAP查询。 |
| 导入数据 | LOAD DATA INPATH 'hdfs:...' INTO TABLE | 将HDFS文件移动到Hive表目录下。 | 实际是HDFS的rename操作,速度快。 |
代码示例⑥:指定表数据存储路径
CREATE TABLE logs (msg STRING) LOCATION '/data/hive/logs';
代码示例⑦:创建内部表
CREATE TABLE employee(id INT, name STRING);
代码示例⑧:创建外部表
CREATE EXTERNAL TABLE ext_logs(...) LOCATION '/raw/logs';
代码示例⑨:分区表插入数据
INSERT INTO logs PARTITION(dt='2025-01-01') VALUES ('error');
-- 数据存于 /data/hive/logs/dt=2025-01-01/
代码示例⑩:指定文件格式
STORED AS PARQUET
代码示例⑪:导入数据
LOAD DATA INPATH '/tmp/data.txt' INTO TABLE staged_data;
7.4 HDFS与HBase的底层依赖
| 组件/机制 | 说明 | 用途 | 注意事项 |
|---|---|---|---|
| HBase Root Directory | hbase.rootdir=hdfs://namenode:9000/hbase | HBase将所有数据(HFile、WAL等)存储在HDFS指定目录下。 | 必须配置为HDFS路径,不可使用本地文件系统。 |
| Write-Ahead Log (WAL) | 存储在HDFS的 /hbase/WALs/ 目录 | 保证数据持久性,RegionServer宕机后可通过WAL恢复未持久化的写操作。 | HDFS的高吞吐和可靠性支撑WAL高效写入。 |
| HFile存储 | 数据块以HFile格式存储在HDFS的 /hbase/data/ 目录 | HBase的底层数据文件由HDFS管理,支持副本机制保障可靠性。 | 每个HFile对应一个HDFS文件,小文件问题较严重。 |
| 元数据存储 | hbase.zookeeper.quorum | HBase元数据(如Region位置)存储在ZooKeeper,而非HDFS。 | HDFS只存数据,ZooKeeper存元数据,实现快速定位。 |
| 备份与恢复 | hbase backup 命令 | 利用HDFS快照或CopyBackup将HBase数据备份到HDFS另一路径或远程集群。 | 支持全量和增量备份。 |
7.5 HDFS与Spark的数据读写
| 方法/API | 语法 | 用途 | 注意事项 |
|---|---|---|---|
| 读取文本文件 | spark.sparkContext.textFile("hdfs://...") | 从HDFS加载文本数据创建RDD。 | 支持通配符(*.log)和压缩文件(.gz, .bz2)。 |
| 读取SequenceFile | spark.sparkContext.sequenceFile[K, V]("hdfs://...") | 读取Hadoop SequenceFile格式数据。 | 需指定键值类型。 |
| 读取Parquet文件 | spark.read.parquet("hdfs://...") | 使用DataFrame API读取列式存储数据,支持谓词下推。 | 性能优越,推荐用于大数据分析。 |
| 写入HDFS | df.write.mode(SaveMode).format(...).save("hdfs://...") | 将DataFrame或RDD保存到HDFS。 | mode可选Append, Overwrite, ErrorIfExists等。 |
| 指定压缩格式 | .option("compression", "snappy/gzip") | 写入文件时启用压缩,节省存储空间。 | Snappy速度快,Gzip压缩率高。 |
| Spark检查点 | spark.sparkContext.setCheckpointDir("hdfs://...") | 设置RDD检查点目录,用于容错恢复。 | 必须使用HDFS等可靠文件系统,本地路径不支持。 |
| 广播变量存储 | 小型只读数据通过HDFS分发 | Spark自动将广播变量从Driver分发到各Executor。 | 实际通过BlockManager在节点间传输,不直接依赖HDFS I/O。 |
代码示例⑫:读取文本文件(Scala)
val rdd = spark.sparkContext.textFile("hdfs://nn:9000/input/")
代码示例⑬:读取SequenceFile(Scala)
val seqRdd = spark.sparkContext.sequenceFile[String, Int]("hdfs://path")
代码示例⑭:读取Parquet文件(Scala)
val df = spark.read.parquet("hdfs://nn:9000/data.parquet")
代码示例⑮:写入HDFS(Scala)
df.write.mode(SaveMode.Overwrite).parquet("hdfs://nn:9000/output/")
代码示例⑯:指定压缩格式写入(Scala)
df.write.option("compression", "snappy").parquet("hdfs://out")
代码示例⑰:Spark检查点(Scala)
spark.sparkContext.setCheckpointDir("hdfs://nn:9000/checkpoint")
代码示例⑱:广播变量(Scala)
val broadVar = spark.sparkContext.broadcast(largeMap)