原文地址:https://jvns.ca/blog/2014/05/15/diving-into-hdfs/
原文标题:Diving into HDFS
原文作者:Julia Evans
原文写于:2014/05/15
译者:驱蚊器喵#ΦωΦ
翻译水平有限,有不通顺的语句,请见谅。
昨天我想开始学习 HDFS (Hadoop 分布式文件系统,Hadoop Distributed File System) 的内部工作方式。我知道的有:
- 它是分布式的,所以一个文件可能被存储在许多不同的机器上
- 有一个 namenode,记录了所有文件的存储位置
- 有一些数据节点(data nodes),存储实际的文件数据
但我不太确定如何开始!我知道如何从命令行中浏览文件系统(hadoop fs -ls /
,以及其他的一些命令),但不知道如何弄清楚它的内部运作。
Colin Marc 给我推荐了伟大的库,叫做 snakebite,是一个 Python HDFS 客户端。特别是他给我指出了从 HDFS 中读取文件内容的那部分代码。我们要把它拆开,看看它到底是做什么的。
从 Elastic MapReduce 开始!
我不想手工建立一个 Hadoop 集群,而且我有一些免费得到的 AWS 余额,所以我建立了一个小型的 Amazon Elastic MapReduce 集群。我与 Pablo Torres 和 Sasha Laundy 一起,我们花了一上午的时间来折腾,试图找出协议版本以及为什么 Snakebite 不能和它兼容。
最终,我们选择了 AMI 版本 “3.0.4(hadoop 2.2.0)”。这是 CDH5 和 Hadoop 协议版本 9。Hadooop 的版本很容易混淆。我们安装了这个版本和 Snakebite 2.4.1 版本,这快要成功了。
重要的事情:
- 我们需要查看
/home/hadoop/conf/core-site.xml
以找到 namenode 的 IP 和端口(在fs.default.name
配置中)。 - 我们需要编辑 snakebite/config.py,将 “fs.default.name” 改为 “fs.defaultFS”。为什么要这么改,我们也不知道,反正最终就是有用。
这样做了后,我们就可以成功地运行snakebite ls /
了! 可以继续拆卸 HDFS 了!
将数据放入我们的集群
我从亚马逊的一个公共数据集中复制了一些维基百科的数据,像这样。
1 | hadoop distcp s3://datasets.elasticmapreduce/wikipediaxml/part-116.xml /wikipedia |
这将在 HDFS 中创建一个名为 /wikipedia
的文件。你可以在 https://s3.amazonaws.com/datasets.elasticmapreduce/ 看到更多可以从亚马逊复制到 HDFS 的数据集。
从文件中获取一个块!
现在我们有了一个 Hadoop 集群,HDFS 中的一些数据,以及一个可以查看这些数据的工具(snakebite),我们可以真正开始了!
HDFS 中的文件被分割成块。当从 HDFS 中获取一个文件时,我们需要做的第一件事就是询问 namenode ,文件的块存储在哪里。
在阅读了大量的 snakebite 代码后,我写了一个小的 Python 函数来做这件事,叫做find_blocks
。你可以在我做的一个叫 hdfs_fun.py 的小 Python 模块中看到它。要让它工作,你需要一个 Hadoop 集群和 snakebite。
1 | cl = hdfs_fun.create_client() |
我做的第一件事是使用 strace
来找出当我调用这个函数时,实际上有哪些数据在传输。下面是一个片段:(整个过程)
请求部分:请求提供 /wikipedia
文件的块位置。
1 | sendto(7, |
响应部分。(我已经删除了大部分内容,只留下了一些重要的部分)
1 | recvfrom(7, |
回到我们的 Python 控制台,我们可以看一下这其中的一些数字是什么意思:
1 | 0].b.poolId blocks[ |
所以我们有两个块! 这两个numBytes
加起来就是这个文件的总大小! 很好! 它们都有相同的 poolId
,而且还发现它们有相同的 IP 地址和端口。
读取文件块
让我们试着从一个块中读取数据吧 (你可以在 hdfs_fun.py 中看到 read_block
函数
1 | 0] block = blocks[ |
如果我用 strace
查看,开头是
1 | connect(8, {sa_family=AF_INET, sin_port=htons(9200), |
很好。我们可以很容易地看到,它正在连接到区块的数据节点(10.147.177.170
,端口为 9200
,并请求提供 id 为BP-1019336183-10.165.43.39-1400088409498
的东西)。然后数据节点开始发回数据!!!。
1 | recvfrom(8, "ot, it's a painting. Thomas Graeme apparently lived in |
不可思议. 我们就这样征服了 HDFS.