Hadoop 是一个由Apache 软件基金会开发的分布式基础架构。用户可以在不了解分布式底层细节的情况下,开发分布式程序,充分利用集群的威力进行高速运算和存储。
Hadoop 实现一个分布式文件系统(Hadoop Distributed File System, HDFS)。HDFS具有高容错性的特点,并设计它用来部署在廉价的硬件上,而且它提供高吞吐量来访问应用程序的数据,适合那些有着超大数据集的应用程序。Hadoop 框架的核心设计是HDFS和MapReduce。HDFS为海量数据提供了存储,而MapReduce则为海量的数据提供了计算。
请参考文章:Centos7 安装Hadoop3 单机版本(伪分布式版本)
HDFS采用Master/Slave架构。
- 一个HDFS集群包含一个单独的NameNode和多个DataNode。
- NameNode作为Master服务,它负责管理文件系统的命名空间和客户端对文件的访问。NameNode会保存文件系统的具体信息,包括文件信息、文件被分割成具体block块的信息、以及每一个block块归属的DataNode的信息。对于整个集群来说,HDFS通过NameNode对用户提供了一个单一的命名空间。
- DataNode作为Slave服务,在集群中可以存在多个。通常每一个DataNode都对应于一个物理节点。DataNode负责管理节点上它们拥有的存储,它将存储划分为多个block块,管理block块信息,同时周期性的将其所有的block块信息发送给NameNode。
HDFS系统架构图,主要有三个角色,Client、NameNode、DataNode。
HDFS的一些关键元素
Client向NameNode发起文件写入的请求。
实例讲解:有一个文件FileA,100M大小。Client将FileA写入到HDFS上。
Hadoop 环境配置说明:
文件写入过程如下:
Client向NameNode发起文件读取的请求。
如图所示,Client要从DataNode上,读取FileA。而FileA由block1和block2组成。读操作流程如下:
上面例子中,Client位于机架外,那么如果Client位于机架内某个DataNode上,例如,Client是host6。那么读取的时候,遵循的规律是:优选读取本机架上的数据。
备份数据的存放是HDFS可靠性和性能的关键。HDFS采用一种称为rack-aware的策略来决定备份数据的存放。
通过一个称为Rack Awareness的过程,NameNode决定每个DataNode所属rack id。
缺省情况下,一个block块会有三个备份:
这种策略综合考虑了同一rack失效、以及不同rack之间数据复制性能问题。
副本的选择:为了降低整体的带宽消耗和读取延时,HDFS会尽量读取最近的副本。如果在同一个rack上有一个副本,那么就读该副本。如果一个HDFS集群跨越多个数据中心,那么将首先尝试读本地数据中心的副本。
调用文件系统(HDFS)Shell命令应使用 bin/hadoop fs
使用方法:hadoop fs -cat URI [URI …]
将路径指定文件的内容输出到stdout。
示例:
返回值:
成功返回0,失败返回-1。
使用方法:hadoop fs -chgrp [-R] GROUP URI [URI …] Change group association of files. With -R, make the change recursively through the directory structure. The user must be the owner of files, or else a super-user. Additional information is in the Permissions User Guide. -->
改变文件所属的组。使用-R将使改变在目录结构下递归进行。命令的使用者必须是文件的所有者或者超级用户。更多的信息请参见HDFS权限用户指南。
使用方法:hadoop fs -chmod [-R]
改变文件的权限。使用-R将使改变在目录结构下递归进行。命令的使用者必须是文件的所有者或者超级用户。更多的信息请参见HDFS权限用户指南。
使用方法:hadoop fs -chown [-R] [OWNER][:[GROUP]] URI [URI ]
改变文件的拥有者。使用-R将使改变在目录结构下递归进行。命令的使用者必须是超级用户。更多的信息请参见HDFS权限用户指南。
使用方法:hadoop fs -copyFromLocal
除了限定源路径是一个本地文件外,和put命令相似。
使用方法:hadoop fs -copyToLocal [-ignorecrc] [-crc] URI
除了限定目标路径是一个本地文件外,和get命令类似。
使用方法:hadoop fs -cp URI [URI …]
将文件从源路径复制到目标路径。这个命令允许有多个源路径,此时目标路径必须是一个目录。
示例:
返回值:
成功返回0,失败返回-1。
使用方法:hadoop fs -du URI [URI …]
显示目录中所有文件的大小,或者当只指定一个文件时,显示此文件的大小。
示例:
hadoop fs -du /user/hadoop/dir1 /user/hadoop/file1 hdfs://host:port/user/hadoop/dir1
返回值:
成功返回0,失败返回-1。
使用方法:hadoop fs -dus
显示文件的大小。
使用方法:hadoop fs -expunge
清空回收站。请参考HDFS设计文档以获取更多关于回收站特性的信息。
使用方法:hadoop fs -get [-ignorecrc] [-crc]
复制文件到本地文件系统。可用-ignorecrc选项复制CRC校验失败的文件。使用-crc选项复制文件以及CRC信息。
示例:
返回值:
成功返回0,失败返回-1。
使用方法:hadoop fs -getmerge
接受一个源目录和一个目标文件作为输入,并且将源目录中所有的文件连接成本地目标文件。addnl是可选的,用于指定在每个文件结尾添加一个换行符。
使用方法:hadoop fs -ls
如果是文件,则按照如下格式返回文件信息:
文件名 <副本数> 文件大小 修改日期 修改时间 权限 用户ID 组ID
如果是目录,则返回它直接子文件的一个列表,就像在Unix中一样。目录返回列表的信息如下:
目录名
使用方法:hadoop fs -lsr
ls命令的递归版本。类似于Unix中的ls -R。
使用方法:hadoop fs -mkdir
接受路径指定的uri作为参数,创建这些目录。其行为类似于Unix的mkdir -p,它会创建路径中的各级父目录。
示例:
返回值:
成功返回0,失败返回-1。
使用方法:dfs -moveFromLocal
输出一个”not implemented“信息。
使用方法:hadoop fs -mv URI [URI …]
将文件从源路径移动到目标路径。这个命令允许有多个源路径,此时目标路径必须是一个目录。不允许在不同的文件系统间移动文件。
示例:
返回值:
成功返回0,失败返回-1。
使用方法:hadoop fs -put
从本地文件系统中复制单个或多个源路径到目标文件系统。也支持从标准输入中读取输入写入目标文件系统。
返回值:
成功返回0,失败返回-1。
使用方法:hadoop fs -rm URI [URI …]
删除指定的文件。只删除非空目录和文件。请参考rmr命令了解递归删除。
示例:
返回值:
成功返回0,失败返回-1。
使用方法:hadoop fs -rmr URI [URI …]
delete的递归版本。
示例:
返回值:
成功返回0,失败返回-1。
使用方法:hadoop fs -setrep [-R]
改变一个文件的副本系数。-R选项用于递归改变目录下所有文件的副本系数。
示例:
返回值:
成功返回0,失败返回-1。
使用方法:hadoop fs -stat URI [URI …]
返回指定路径的统计信息。
示例:
返回值:
成功返回0,失败返回-1。
使用方法:hadoop fs -tail [-f] URI
将文件尾部1K字节的内容输出到stdout。支持-f选项,行为和Unix中一致。
示例:
返回值:
成功返回0,失败返回-1。
使用方法:hadoop fs -test -[ezd] URI
选项:
-e 检查文件是否存在。如果存在则返回0。
-z 检查文件是否是0字节。如果是则返回0。
-d 如果路径是个目录,则返回1,否则返回0。
示例:
使用方法:hadoop fs -text
将源文件输出为文本格式。允许的格式是zip和TextRecordInputStream。
使用方法:hadoop fs -touchz URI [URI …]
创建一个0字节的空文件。
示例:
返回值:
成功返回0,失败返回-1。
HDFS 除了通过HDFS Shell 命令的方式进行操作,还可以通过Java API、Python API、C++ API等方式进行编程操作。在使用Python API 编程前,需要安装HDFS 依赖的第三方库:PyHDFS
官方文档地址:https://pyhdfs.readthedocs.io/en/latest/pyhdfs.html
原文简介:
WebHDFS client with support for NN HA and automatic error checking
For details on the WebHDFS endpoints, see the Hadoop documentation:
https://hadoop.apache.org/docs/current/hadoop-project-dist/hadoop-hdfs/WebHDFS.html
https://hadoop.apache.org/docs/current/api/org/apache/hadoop/fs/FileSystem.html
https://hadoop.apache.org/docs/current/hadoop-project-dist/hadoop-common/filesystem/filesystem.html
大致意思是:pyhdfs 模块/库使用WebHDFS 客户端连接HDFS,支持NN HA 和自动错误检测,详细使用参考官方文档地址。
安装pyhdfs 模块/库
pip install pyhdfs
pyhdfs 使用实例
# _*_ coding : UTF-8_*_
# 开发者 : zhuozhiwengang
# 开发时间 : 2023/8/11 22:35
# 文件名称 : pythonHdfs_1
# 开发工具 : PyCharm
import pyhdfs
# 基于pyHDFS 模块, 连接Hadoop 主机:9870 端口
fs = pyhdfs.HdfsClient(hosts="192.168.43.11:9870", user_name="root")
# 返回用户根目录
print(fs.get_home_directory())
# 返回可用namenode节点
print(fs.get_active_namenode())
# 返回指定目录下所有文件
print(fs.listdir("/"))
# hadoop 创建指定目录
fs.mkdirs('/uploads')
# 再次执行返货指定目录下所有文件
print(fs.listdir("/"))
# 执行本地文件上传Hadoop 指定目录
# fs.copy_from_local("D:\one.txt", '/uploads/one.txt')
# 执行Hadoop 文件下载
# fs.copy_to_local("/uploads/one.txt", r'D:\two.txt')
# 判断目录是否存在
print(fs.exists("/uploads"))
# 返回目录下的所有目录,路径,文件名
print(list(fs.walk('/uploads')))
# 删除目录/文件
fs.delete("/uploads", recursive=True) # 删除目录 recursive=True
fs.delete("/uploads/one.txt") # 删除文件
# _*_ coding : UTF-8_*_
# 开发者 : zhuozhiwengang
# 开发时间 : 2023/8/11 22:35
# 文件名称 : pythonHdfs
# 开发工具 : PyCharm
import sys
import pyhdfs
class HDFS:
def __init__(self, host='192.168.43.11',user_name='root'):
self.host = host
self.user_name=user_name
def get_con(self):
try:
hdfs = pyhdfs.HdfsClient(hosts = self.host,user_name = self.user_name)
return hdfs
except pyhdfs.HdfsException,e:
print "Error:%s" % e
# 返回指定目录下的所有文件
def listdir(self,oper):
try:
client = self.get_con()
dirs = client.listdir(oper)
for row in dirs:
print row
except pyhdfs.HdfsException, e:
print "Error:%s" % e
# 返回用户的根目录
def get_home_directory(self):
try:
client = self.get_con()
print client.get_home_directory()
except pyhdfs.HdfsException, e:
print "Error:%s" % e
# 返回可用的namenode节点
def get_active_namenode(self):
try:
client = self.get_con()
print client.get_active_namenode()
except pyhdfs.HdfsException, e:
print "Error:%s" % e
# 创建新目录
def mkdirs(self,oper):
try:
client = self.get_con()
print client.mkdirs(oper)
except pyhdfs.HdfsException, e:
print "Error:%s" % e
# 从集群上copy到本地
def copy_to_local(self, dest,localsrc):
try:
client = self.get_con()
print client.copy_to_local(dest,localsrc)
except pyhdfs.HdfsException, e:
print "Error:%s" % e
# 从本地上传文件至集群
def copy_from_local(self, localsrc, dest):
try:
client = self.get_con()
print client.copy_from_local(localsrc, dest)
except pyhdfs.HdfsException, e:
print "Error:%s" % e
# 查看文件内容
def read_files(self,oper):
try:
client = self.get_con()
response = client.open(oper)
print response.read()
except pyhdfs.HdfsException, e:
print "Error:%s" % e
# 向一个已经存在的文件追加内容
def append_files(self, file,content):
try:
client = self.get_con()
print client.append(file,content)
except pyhdfs.HdfsException, e:
print "Error:%s" % e
# 查看是否存在文件
def check_files(self,oper):
try:
client = self.get_con()
print client.exists(oper)
except pyhdfs.HdfsException, e:
print "Error:%s" % e
# 查看文件的校验和
def get_file_checksum(self,oper):
try:
client = self.get_con()
print client.get_file_checksum(oper)
except pyhdfs.HdfsException, e:
print "Error:%s" % e
# 查看路径总览信息
def get_content_summary(self,oper):
try:
client = self.get_con()
print client.get_content_summary(oper)
except pyhdfs.HdfsException, e:
print "Error:%s" % e
# 查看当前路径的状态
def list_status(self,oper):
try:
client = self.get_con()
print client.list_status(oper)
except pyhdfs.HdfsException, e:
print "Error:%s" % e
# 删除文件
def delete_files(self,path):
try:
client = self.get_con()
print client.delete(path)
except pyhdfs.HdfsException, e:
print "Error:%s" % e
if __name__ == '__main__':
db = HDFS('Hadoop3-master','root')
# db.listdir('/user')
# db.get_home_directory()
# db.get_active_namenode()
# db.mkdirs('/dave')
# db.copy_from_local("D:/one.txt","/uploads/two.txt")
# db.listdir('/uploads')
# db.read_files('/uploads/two.txt')
# db.check_files('/uploads/two.txt')
# db.get_file_checksum('/uploads/two.txt')
# db.get_content_summary('/')
# db.list_status('/')
# db.list_status('/uploads/two.txt')
# db.copy_to_local("/uploads/two.txt","D:/one.txt")
# db.append_files('/uploads/two.txt',"88, CSDN 博客")
# db.read_files('/uploads/two.txt')
# db.copy_from_local("D:/three.txt", "/uploads/two.txt")
db.listdir('/uploads')
# db.delete_files('/uploads/two.txt')