Apache Hadoop — 在一个 Pod 里搭起并运维 HDFS 与 YARN
复现 1 字节文件为何被 30MB 配额挡住
目标
给目录设置名称配额和空间配额,并通过拒绝消息确认:名称配额连目录自身也要计数,空间配额会按块大小 × 副本系数提前预留。缩小块大小让同一个文件写进去,同时看到配额连移动(mv)也会拦。
为什么重要
多个团队共用一个 HDFS 时,某个团队的失误(无限创建文件的作业、数百万个小文件)会把 NameNode 的堆和磁盘从所有人手里抢走。配额就是把这种损害限制在一个目录内的装置。名称配额限制文件和目录的数量,空间配额限制连副本一起计算的字节数。 空间配额有一个陷阱。开始写文件时,NameNode 还不知道要写多少字节,所以会把一整个块(块大小 × 副本系数)预留下来。因此,剩余配额如果小于 128MB,连 1 字节的文件也写不进去。写入结束后会按实际大小结算,但连开始都做不到就没用了。在生产环境中,“配额还有剩,为什么写不了”这类咨询,大部分就是这个原因。 配额对所有产生新名字的操作都生效。从别的目录移进来,对这个目录而言也是一个新名字。
步骤
- 创建 HDFS 的 /quota/team-a,并设置名称配额 10(
hdfs dfsadmin -setQuota)。 - 把小的本地文件逐个上传到 team-a,直到被拒绝为止,并把被拒绝的
put的错误输出保存到 /root/hdp/quota/quota_err.txt。 - 创建 /quota/team-b 并设置 30MB 的空间配额(
hdfs dfsadmin -setSpaceQuota 30m)。 - 创建 1 字节的本地文件 /root/hdp/quota/one.txt,尝试把它上传为 /quota/team-b/one.txt,并把错误输出保存到 /root/hdp/quota/space_err.txt。
- 以 1MiB 的块大小(
-D dfs.blocksize=1048576)把同一个文件上传为 /quota/team-b/one-1m.txt。 - 把
hdfs dfs -count -q -v /quota/team-a /quota/team-b的输出保存到 /root/hdp/quota/count.txt。 - 创建 /quota/staging 并上传一个文件(/quota/staging/f.txt),然后尝试用
-mv把它移到 team-a,并把错误输出保存到 /root/hdp/quota/mv_err.txt。 - 在 /root/hdp/quota/report.md 中写出
## 이름 쿼터、## 공간 쿼터、## 쿼터가 막는 것三个小节。第一节写入实际放进 team-a 的文件数,第二节写入试图预留的字节数(134217728)。
参考
- 设置配额属于管理员命令(
hdfs dfsadmin),只有超级用户才能执行。在这个 Pod 中就是 root。 - 空间配额的单位是字节,可以使用
30m、1g这样的后缀。副本也要计算——副本系数为 3 时,1MB 的文件会占用 3MB。 -count -q的各列:QUOTA · REM_QUOTA · SPACE_QUOTA · REM_SPACE_QUOTA · DIR_COUNT · FILE_COUNT · CONTENT_SIZE · PATHNAME。- 常见错误:以为名称配额为 10 就能放进 10 个文件,以及只看空间配额的剩余量就判断能写入。
- 官方文档:HDFS Quotas Guide · HDFS Commands — dfsadmin · FileSystem Shell — count · WebHDFS — Get Content Summary
设置名称配额
创建 HDFS 的 /quota/team-a,并用 hdfs dfsadmin -setQuota 10 /quota/team-a 设置名称配额 10。
名称配额是该目录之下(包括自身)的文件和目录数量上限。设置的值可以在 hdfs dfs -count -q 的第一列看到。
配额是 10,能放进几个
创建多个小的本地文件,逐个用 hdfs dfs -put 上传到 /quota/team-a/,并把被拒绝的 put 的错误输出(标准错误)保存到 /root/hdp/quota/quota_err.txt。
目录自身也算作一个名字。所以文件比配额少放一个。拒绝消息里会同时打印出配额和“放入之后的数量”。
设置空间配额
创建 HDFS 的 /quota/team-b,并用 hdfs dfsadmin -setSpaceQuota 30m /quota/team-b 设置 30MB 的空间配额。
30m 就是 30 × 1024 × 1024 字节。空间配额是对连副本一起计算的实际磁盘使用量设置的上限。
1 字节也被拦住
创建 1 字节的本地文件 /root/hdp/quota/one.txt(printf x > /root/hdp/quota/one.txt),并尝试用 hdfs dfs -put 把它上传为 /quota/team-b/one.txt。把错误输出保存到 /root/hdp/quota/space_err.txt。
开始写入的那一刻,NameNode 会预留一个块(块大小 × 副本系数)。默认的块大小 128MB 比 30MB 的配额还大。请对比消息中的两个数字——配额和所需的空间。
把块设小就能写入
用 hdfs dfs -D dfs.blocksize=1048576 -put 把同一个 /root/hdp/quota/one.txt 上传为 /quota/team-b/one-1m.txt。
块大小是 1MiB 时,预留也是 1MiB。写入结束后,使用量按实际大小(1 字节 × 副本系数)结算。请看 -count -q 中的 REM_SPACE_QUOTA 减少了多少。
用 count -q 读取两种配额
把 hdfs dfs -count -q -v /quota/team-a /quota/team-b 的输出保存到 /root/hdp/quota/count.txt。
没有配额的栏会显示为 none/inf。team-a 的 REM_QUOTA 是 0,而 team-b 的空间几乎原封不动地剩着——被拒绝的原因不是“剩余量”,而是“要预留的量”。
移动也会受配额限制
创建 HDFS 的 /quota/staging,上传一个文件为 /quota/staging/f.txt,然后尝试 hdfs dfs -mv /quota/staging/f.txt /quota/team-a/,并把错误输出保存到 /root/hdp/quota/mv_err.txt。
移动并不搬动字节,但对 team-a 来说,名字多了一个。所以名称配额会拒绝,文件仍然留在 staging 中。
学会回答配额咨询
在 /root/hdp/quota/report.md 中写出 ## 이름 쿼터、## 공간 쿼터、## 쿼터가 막는 것 三个小节。第一节写入实际放进 team-a 的文件数,第二节以数字写入第 4 步中试图预留的字节数。
请想象自己在回答这样的咨询:“配额是 10,为什么只能放进 9 个?”、“还剩 30MB,为什么连 1 字节都写不了?”,然后写出答案。