沿着 HDFS 数据块追踪文件

大数据Beginner
立即练习

介绍

零售商的文件有名称和目录,但机器还必须把文件内容保存在某个地方。一个大文件怎样分散到多个存储节点上?HDFS 保留副本时复制的是什么?一个几乎为空的块,会占用整个块大小的磁盘空间吗?

你已经知道如何组织和保留文件。本实验将带你观察路径之下的存储。HDFS 块(block)是文件的一部分,由 HDFS 跟踪和存储。NameNode 保存文件和块位置的元数据,DataNode 保存块数据。副本(replica)是块的另一份存储拷贝,并不是新的零售记录,也不是另一个用户可见的文件。

你将使用一个特意选定、较小且有效的块大小上传两个预置文件,预测块数,并检查真实位置。这个只有一个 DataNode 的环境使用副本数 1。它提供真实的观察结果,但不会演示多机恢复。所有数据和服务均独立准备。请使用终端,无需编程。

将文件大小与数据块联系起来

在这一步中,你将使用已知的块大小上传一个文件,并检查它的元数据。

文件系统路径为逻辑文件命名。HDFS 将其内容分成块,这样在较大集群中,不同部分就可以存储在不同 DataNode 上。配置的块大小是该块能够容纳的数据上限,并不表示每个块都会填满。

进入项目目录:

cd /home/labex/project

本地命令 wc -c 统计字节数。用它检查第一个预置文件:

wc -c /home/labex/project/data/products-a.txt

结果以 1572864 开头,恰好是 1.5 MiB。一个 MiB 等于 1,048,576 字节。这个文件重复使用简单的商品标签,让存储实验不涉及复杂的业务规则。

创建自己的 HDFS 目录:

hdfs dfs -mkdir -p /user/labex/block-study

本次演示中,-Ddfs.blocksize=1048576 会覆盖接下来这次上传使用的客户端块大小设置。-D 为本条命令提供配置属性,不会编辑共享配置文件。1 MiB 满足该镜像的最小块大小限制,也能让演示保持较小规模:

hdfs dfs -Ddfs.blocksize=1048576 -put /home/labex/project/data/products-a.txt /user/labex/block-study/products-a.txt

预测一下存储布局:1.5 MiB 的文件使用 1 MiB 的块大小,需要一个满块和一个半满块,共两个块。

HDFS 的 -stat 操作输出所选元数据。在引号包围的格式中,%b 表示以字节为单位的文件长度,%o 表示块大小,%r 表示副本数:

hdfs dfs -stat 'bytes=%b blocksize=%o replication=%r' /user/labex/block-study/products-a.txt

预期值如下:

bytes=1572864 blocksize=1048576 replication=1

文件长度仍为 1.5 MiB。副本数 1 表示每个块有一份存储拷贝,并不表示整个文件只有一个块。保存实际元数据:

hdfs dfs -stat 'bytes=%b blocksize=%o replication=%r' /user/labex/block-study/products-a.txt > /home/labex/project/output/file-a-metadata.txt

如果之前已完成上传、文件已存在,请先检查它,再考虑重复上传;不要仅仅因为 -put 提示目标已存在就删除文件。

检查位置并预测变化

在这一步中,你将找到第一个文件的真实数据块,并使用更大的文件检验预测。

hdfs fsck 命令可以检查文件的存储状态。在下面的只读检查中,-files 显示文件详细信息,-blocks 显示块信息,-locations 显示保存各块的 DataNode。这些选项都不会修复或删除文件:

hdfs fsck /user/labex/block-study/products-a.txt -files -blocks -locations

找到文件长度行、块条目,以及汇总中的 Total blocks (validated) 字段。应该有两个块,一个包含 1,048,576 字节,另一个包含 524,288 字节。块标识符、地址和时间戳会变化。最终的文件系统健康汇总应该为 HEALTHY。

保存检查结果:

hdfs fsck /user/labex/block-study/products-a.txt -files -blocks -locations > /home/labex/project/output/file-a-blocks.txt

健康结果表示本次检查找到了所需的块和副本。每个块只有一份副本,并且位于同一台机器上,因此不代表丢失该机器后文件仍能保留。

现在检查第二个本地文件的大小:

wc -c /home/labex/project/data/products-b.txt

它的长度是 2621440 字节,即 2.5 MiB。上传之前,预测在同样的 1 MiB 块大小下,它会有多少块、各有多大。这次只改变文件长度:

hdfs dfs -Ddfs.blocksize=1048576 -put /home/labex/project/data/products-b.txt /user/labex/block-study/products-b.txt

检查结果:

hdfs fsck /user/labex/block-study/products-b.txt -files -blocks -locations

应该找到三个块:两个满块和一个 524,288 字节的块。本实验中的所有位置都指向同一个 DataNode。保存观察结果:

hdfs fsck /user/labex/block-study/products-b.txt -files -blocks -locations > /home/labex/project/output/file-b-blocks.txt

在更大的集群中,块的位置可以分布在不同机器上。NameNode 向客户端提供位置元数据;它不是所有文件内容字节都必须经过的中央通道。

理解空间、副本与数据传输路径

在这一步中,你将把块的观察结果与文件大小和实际的存储节点报告联系起来。

最后一个块只有半满时,不会仅因块大小设置为 1 MiB,就预留整整 1 MiB 的数据空间。使用不带 -h 的 -du,显示精确的字节数:

hdfs dfs -du /user/labex/block-study

每个文件的前两列应该是:

1572864  1572864  .../products-a.txt
2621440  2621440  .../products-b.txt

第一列是逻辑文件长度,第二列计入副本。这里副本数为 1,因此两列相同。这些值描述的是 HDFS 文件数据,并不包含所有文件系统元数据字节,也不代表虚拟机的总磁盘用量。保存这些行:

hdfs dfs -du /user/labex/block-study > /home/labex/project/output/block-report.txt

使用环境认识实验中介绍过的只读管理命令,查看实际存储节点报告:

sudo -u hdfs /usr/local/bin/hdfs dfsadmin -report

查找 Live datanodes (1)。将副本数设为 3 并不会创建三台机器;本实验将副本数保持为 1,避免数据块一直等待不存在的副本位置。

将观察结果与数据传输路径联系起来:

写入:客户端请求 NameNode 创建文件,然后将块数据发送给 DataNode。
读取:客户端向 NameNode 查询位置,然后从 DataNode 读取块数据。

在更大的集群中有多个副本时,客户端可以使用可用的拷贝,处理框架也可以尝试在靠近数据的位置执行任务。这个概念称为数据局部性(data locality)。使用 -cp 创建的命名副本是第二个逻辑文件;块副本则是一个逻辑文件内部数据块的存储拷贝。它们解决的是不同问题。

预测练习改变的是文件大小,而不是副本数。文件 A 仍有两个块,文件 B 有三个块,两者的每个块都各有一份副本。接下来,你将学习为什么文件已经存在且健康,某个用户却仍然无法读取它:原因在于访问权限。

总结

你预测并观察了 1.5 MiB 和 2.5 MiB 的文件如何分别拆分成两个和三个 1 MiB 数据块。你检查了真实的块位置,并区分了逻辑文件长度、副本存储空间和额外的命名文件。

你还将这些结果与 NameNode 元数据和 DataNode 数据传输联系起来。单节点环境展示了这些职责,而多机容量与容错则留待后续探索。