HDFS课程

来源:互联网 发布:软件外包是什么 编辑:程序博客网 时间:2024/05/21 17:52

HDFS定义

源自于Google的GFS论文
发表于2003年10月
HDFS是GFS的克隆版

Hadoop Distributed File System
易于扩展的分布式文件系统
运行在大量普通廉价机器上,提供容错机制
为大量用户提供性能不错的文件存取服务

HDFS设计目标

非常巨大的分布式文件系统
万个以上的节点,亿份以上文件,10PB的容量以上
1 ZB = 1024 EB
1 EB = 1024 PB
1 PB = 1024 TB
1 TB = 1024 GB
1 GB = 1024 MB

运行于普通硬件上
文件复制多份,避免硬件失败
探测失败和错误恢复

优化批处理
数据暴漏位置,以便计算能够挪到数据附近
提供高聚合的带宽

用户空间可以位于异构的操作系统中

在整个集群中使用单个的命名空间

数据一致性
“写入一次读取多次”的访问模型
客户端只能追加已有的文件

文件被分成各个小块
默认每一块是64MB(实际生产可以调大,一般都是64的整数倍,128是最好的)
每一块复制到不同的DataNode上

智能的客户端
客户端能找到文件块的位置
客户端能直接访问DataNode中的文件位置

程序采用数据就近原则分配节点执行

客户端对文件没有缓存机制(No data caching)

我的H01HDFS

http://192.168.108.101:50070/dfshealth.jsp

我的H01MapReduce

http://192.168.108.101:50030/jobtracker.jsp

HDFS架构——文件

文件切分成块(默认大小64M),以块为单位,每个块有多个副本存储在不同的机器上。副本数可在文件生成时指定(默认3)。

NameNode是主节点,存储文件的元数据:如文件名,文件目录结构,文件属性(生成时间,副本数,文件权限),以及每个文件的块列表、块列表所在的DataNode等等

DataNode在本地文件系统存储文件块数据,以及块数据的校验和。

可以创建、删除、移动或命名文件,当文件创建、写入和关闭之后不能修改文件内容。
这里写图片描述

HDFS架构——NameNode

NameNode是一个中心服务器,单一节点(简化系统的设计与实现),负责管理文件系统的名字空间(namespace)以及客户端对文件的访问。

文件操作,NameNode负责文件元数据的操作,DataNode负责处理文件内容的读写请求,跟文件内容相关的数据流不经过NameNode,只会询问它跟哪个DataNode联系,否则NameNode会成为系统的瓶颈。

副本存放在哪些DataNode上由NameNode来控制。根据全局情况做出块放置决定,读取文件时NameNode尽量让用户先读取最近的副本,降低带宽消耗和读取延时。

NameNode全权管理数据块的复制,它周期性的从集群中的每个DataNode接收心跳信号和块状态报告(Blockreport)。接收心跳信号意味着该DataNode节点工作正常。块状态报告包含了一个该DataNode上所有数据的块列表。

HDFS架构——DataNode

一个数据块在DataNode以文件存储在磁盘上,包括两个文件,一个是数据本身,一个是元数据包括数据块的长度,块数据的校验和,以及时间戳。

DataNode启动后向NameNode注册,通过后,周期性(1小时)的向NameNode上报告所有的块信息。

心跳是每3秒一下,心跳返回结果带有NameNode给该DataNode的命令如复制块数据到另一台机器上,或删除某个数据块。如果超过10分钟没有收到某个DataNode的心跳,则认为该节点不可用。

集群运行中可以安全加入和退出一些机器。

HDFS架构——NN & SNN

NameNode的两个重要文件
fsimage:元数据镜像文件(保存文件系统的目录树)
edits:元数据操作日志(针对目录树的修改操作)

元数据镜像
内存中保存一份最新的
内存中的镜像=fsimage+edits

定期合并fsimage与edits
Edits文件过大将导致NameNode重启速度慢
SecondaryNameNode负责定期合并它们

这里写图片描述

第一步,SecondaryNameNode通知NameNode切换editlog

第二布,SecondaryNameNode从NameNode获得fsimage和editlog(通过http方式)

第三步,SecondaryNameNode将fsimage载入内存,然后开始合并editlog

第四步,SecondaryNameNode将新的fsimage发回给NameNode

第五步,NameNode用新的fsimage替换旧的fsimage并进行改名

HDFS Shell命令

调用文件系统(FS)Shell命令使用bin/hadoop fs 的形式

所有的FS Shell命令使用URI路径作为参数

URI格式是scheme://authority/path。HDFS的scheme是hdfs;对于本地文件系统,scheme是file。其中scheme和authority参数都是可选的,如果未加指定,就会使用配置中指定的默认scheme。

例如:/parent/child可以表示成
hdfs://namenode:namenodePort/parent/child,或者更简单的/parent/child(假设配置文件是namenode:namenodePort)

大多数的FS Shell命令的行为和对应的Unix Shell命令相似

[hadoop1@H01 ~]$ hadoop fs -helphadoop fs is the command to execute fs commands. The full syntax is: hadoop fs [-fs <local | file system URI>] [-conf <configuration file>]    [-D <property=value>] [-ls <path>] [-lsr <path>] [-du <path>]    [-dus <path>] [-mv <src> <dst>] [-cp <src> <dst>] [-rm [-skipTrash] <src>]    [-rmr [-skipTrash] <src>] [-put <localsrc> ... <dst>] [-copyFromLocal <localsrc> ... <dst>]    [-moveFromLocal <localsrc> ... <dst>] [-get [-ignoreCrc] [-crc] <src> <localdst>    [-getmerge <src> <localdst> [addnl]] [-cat <src>]    [-copyToLocal [-ignoreCrc] [-crc] <src> <localdst>] [-moveToLocal <src> <localdst>]    [-mkdir <path>] [-report] [-setrep [-R] [-w] <rep> <path/file>]    [-touchz <path>] [-test -[ezd] <path>] [-stat [format] <path>]    [-tail [-f] <path>] [-text <path>]    [-chmod [-R] <MODE[,MODE]... | OCTALMODE> PATH...]    [-chown [-R] [OWNER][:[GROUP]] PATH...]    [-chgrp [-R] GROUP PATH...]    [-count[-q] <path>]    [-help [cmd]]-fs [local | <file system URI>]:    Specify the file system to use.        If not specified, the current configuration is used,         taken from the following, in increasing precedence:             core-default.xml inside the hadoop jar file             core-site.xml in $HADOOP_CONF_DIR         'local' means use the local file system as your DFS.         <file system URI> specifies a particular file system to         contact. This argument is optional but if used must appear        appear first on the command line.  Exactly one additional        argument must be specified. -ls <path>:     List the contents that match the specified file pattern. If        path is not specified, the contents of /user/<currentUser>        will be listed. Directory entries are of the form             dirName (full path) <dir>         and file entries are of the form             fileName(full path) <r n> size         where n is the number of replicas specified for the file         and size is the size of the file, in bytes.-lsr <path>:    Recursively list the contents that match the specified        file pattern.  Behaves very similarly to hadoop fs -ls,        except that the data is shown for all the entries in the        subtree.-du <path>:     Show the amount of space, in bytes, used by the files that         match the specified file pattern.  Equivalent to the unix        command "du -sb <path>/*" in case of a directory,         and to "du -b <path>" in case of a file.        The output is in the form             name(full path) size (in bytes)-dus <path>:    Show the amount of space, in bytes, used by the files that         match the specified file pattern.  Equivalent to the unix        command "du -sb"  The output is in the form             name(full path) size (in bytes)-mv <src> <dst>:   Move files that match the specified file pattern <src>        to a destination <dst>.  When moving multiple files, the         destination must be a directory. -cp <src> <dst>:   Copy files that match the file pattern <src> to a         destination.  When copying multiple files, the destination        must be a directory. -rm [-skipTrash] <src>:     Delete all files that match the specified file pattern.        Equivalent to the Unix command "rm <src>"        -skipTrash option bypasses trash, if enabled, and immediatelydeletes <src>-rmr [-skipTrash] <src>:    Remove all directories which match the specified file         pattern. Equivalent to the Unix command "rm -rf <src>"        -skipTrash option bypasses trash, if enabled, and immediatelydeletes <src>-put <localsrc> ... <dst>:  Copy files from the local file system         into fs. -copyFromLocal <localsrc> ... <dst>: Identical to the -put command.-moveFromLocal <localsrc> ... <dst>: Same as -put, except that the source is        deleted after it's copied.-get [-ignoreCrc] [-crc] <src> <localdst>:  Copy files that match the file pattern <src>         to the local name.  <src> is kept.  When copying mutiple,         files, the destination must be a directory. -getmerge <src> <localdst>:  Get all the files in the directories that         match the source file pattern and merge and sort them to only        one file on local fs. <src> is kept.-cat <src>:     Fetch all files that match the file pattern <src>         and display their content on stdout.-copyToLocal [-ignoreCrc] [-crc] <src> <localdst>:  Identical to the -get command.-moveToLocal <src> <localdst>:  Not implemented yet -mkdir <path>:  Create a directory in specified location. -setrep [-R] [-w] <rep> <path/file>:  Set the replication level of a file.         The -R flag requests a recursive change of replication level         for an entire tree.-tail [-f] <file>:  Show the last 1KB of the file.         The -f option shows apended data as the file grows. -touchz <path>: Write a timestamp in yyyy-MM-dd HH:mm:ss format        in a file at <path>. An error is returned if the file exists with non-zero length-test -[ezd] <path>: If file { exists, has zero length, is a directory        then return 0, else return 1.-text <src>:    Takes a source file and outputs the file in text format.        The allowed formats are zip and TextRecordInputStream.-stat [format] <path>: Print statistics about the file/directory at <path>        in the specified format. Format accepts filesize in blocks (%b), filename (%n),        block size (%o), replication (%r), modification date (%y, %Y)-chmod [-R] <MODE[,MODE]... | OCTALMODE> PATH...        Changes permissions of a file.        This works similar to shell's chmod with a few exceptions.    -R  modifies the files recursively. This is the only option        currently supported.    MODE    Mode is same as mode used for chmod shell command.        Only letters recognized are 'rwxX'. E.g. a+r,g-w,+rwx,o=r    OCTALMODE Mode specifed in 3 digits. Unlike shell command,        this requires all three digits.        E.g. 754 is same as u=rwx,g=rx,o=r        If none of 'augo' is specified, 'a' is assumed and unlike        shell command, no umask is applied.-chown [-R] [OWNER][:[GROUP]] PATH...        Changes owner and group of a file.        This is similar to shell's chown with a few exceptions.    -R  modifies the files recursively. This is the only option        currently supported.        If only owner or group is specified then only owner or        group is modified.        The owner and group names may only cosists of digits, alphabet,        and any of '-_.@/' i.e. [-_.@/a-zA-Z0-9]. The names are case        sensitive.        WARNING: Avoid using '.' to separate user name and group though        Linux allows it. If user names have dots in them and you are        using local file system, you might see surprising results since        shell command 'chown' is used for local files.-chgrp [-R] GROUP PATH...        This is equivalent to -chown ... :GROUP ...-count[-q] <path>: Count the number of directories, files and bytes under the paths        that match the specified file pattern.  The output columns are:        DIR_COUNT FILE_COUNT CONTENT_SIZE FILE_NAME or        QUOTA REMAINING_QUATA SPACE_QUOTA REMAINING_SPACE_QUOTA               DIR_COUNT FILE_COUNT CONTENT_SIZE FILE_NAME-help [cmd]:    Displays help for given command or all commands if none        is specified.

关于FS命令:

[hadoop1@H01 data]$ ls1.data[hadoop1@H01 data]$ touch 2.txt[hadoop1@H01 data]$ ls1.data  2.txt[hadoop1@H01 data]$ vim 2.txt [hadoop1@H01 data]$ hadoop fs -mkdir /dataa[hadoop1@H01 data]$ hadoop fs -put 2.txt /dataa[hadoop1@H01 data]$ hadoop fs -ls /Found 2 items-rw-r--r--   1 hadoop1 supergroup         15 2015-10-21 14:13 /datadrwxr-xr-x   - hadoop1 supergroup          0 2015-10-21 14:22 /dataa[hadoop1@H01 data]$ hadoop fs -ls /dataaFound 1 items-rw-r--r--   1 hadoop1 supergroup         11 2015-10-21 14:22 /dataa/2.txt[hadoop1@H01 data]$ hadoop fs -ls /dataFound 1 items-rw-r--r--   1 hadoop1 supergroup         15 2015-10-21 14:13 /data[hadoop1@H01 data]$ hadoop fs -mkdir /data2[hadoop1@H01 data]$ hadoop fs -mv /data /data2[hadoop1@H01 data]$ hadoop fs -ls /Found 2 itemsdrwxr-xr-x   - hadoop1 supergroup          0 2015-10-21 14:25 /data2drwxr-xr-x   - hadoop1 supergroup          0 2015-10-21 14:22 /dataa[hadoop1@H01 data]$ hadoop fs -ls /dataaFound 1 items-rw-r--r--   1 hadoop1 supergroup         11 2015-10-21 14:22 /dataa/2.txt[hadoop1@H01 data]$ hadoop fs -ls /data2Found 1 items-rw-r--r--   1 hadoop1 supergroup         15 2015-10-21 14:13 /data2/data[hadoop1@H01 data]$ [hadoop1@H01 data]$ hadoop fs -cat /data2/dataHello Hadoop ![hadoop1@H01 data]$ hadoop fs -cat /data2cat: File does not exist: /data2[hadoop1@H01 data]$ hadoop fs -cat /data2/dataHello Hadoop ![hadoop1@H01 data]$ hadoop fs -cat /dataa/2.txtwobuzhidao[hadoop1@H01 data]$ 

HDFS文件读取流程

这里写图片描述

Cleint调用FileSystem.open()方法:

1)FileSystem通过RPC(就是整个HDFS各个进程之间的通信的协议)与NN通信,NN返回该文件的部分或全部block列表(含有block拷贝的DN地址)。

2)选取距离客户端最近的DN建立连接,读取block,返回FSDataInputStream。

Client调用输入流的read()方法

1)当读到block的结尾时,FSDataInputSystem关闭与当前DN的连接,并为读取下一个block寻找最近的DN。

2)读取完一个block都会进行checksum验证,如果读取DN时出现错误,客户端会通知NN,然后再从下一个拥有该block拷贝的DN继续读。

3)如果block列表读完后,文件还未结束,FileSystem会继续从NN获取下一批block列表。

关闭FSDataInputSystem

HDFS文件写入流程

这里写图片描述

Client调用FileSystem的create()方法:

1)FileSystem向NN发送请求,在NN的namespace里面创建一个新文件,但是并不关联任何块。

2)NN检查文件是否已存在、操作权限。如果检查通过,NN记录新文件信息,并在某一个DN上创建数据块。

3)返回FSDataOutputStream,将Client引导至该数据块执行写入操作。

Client调用输出流的write()方法:

HDFS默认将每个数据块放置3份。FSDataOutputStream将数据首先写到第一节点,第一节点将数据包传送并写入第二节点,第二节点再到第三节点。

Client调用流的close()方法:flush缓冲区的数据包,block完成复制份数后,NN返回成功消息。

HDFS代码包

HDFS 工具类包

package hadoop.hdfs.utils;import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.fs.FileSystem;/** * HDFS 工具类包 * */public class HDFSUtils {    public static FileSystem getFileSystem() {        // 声明 FileSystem        FileSystem hdfs = null;        try {            // 获取配置文件信息            Configuration conf = new Configuration();            // 获取文件系统            hdfs = FileSystem.get(conf);        } catch (Exception e) {            e.printStackTrace();        }        return hdfs;    }}

HDFS API URL 方式操作

package hadoop.hdfs;import java.io.InputStream;import java.net.URL;import org.apache.hadoop.fs.FsUrlStreamHandlerFactory;import org.apache.hadoop.io.IOUtils;import org.junit.Test;/** * HDFS API URL 方式操作 *  * */public class HDFSUrlTest {    // 让java程序识别HDFS的URL。    static {        URL.setURLStreamHandlerFactory(new FsUrlStreamHandlerFactory());    }    // 查看文件内容,与HDFSFsTest的testRead方法功能一样    @Test    public void testRead() throws Exception {        InputStream in = null;        // 文件路径        String fileUrl = "hdfs://H01:9000/data2/data";        try {            // 获取文件输入流            in = new URL(fileUrl).openStream();            // 将文件内容读取出来打印在控制台            IOUtils.copyBytes(in, System.out, 4096, false);        } finally {            IOUtils.closeStream(in);        }    }}

通过FileSystem API 操作HDFS的10个方法

注意:在Shell命令对HDFS上的文件进行操作的时候,要注意写全文件的路径

package hadoop.hdfs;import org.apache.hadoop.fs.BlockLocation;import org.apache.hadoop.fs.FSDataInputStream;import org.apache.hadoop.fs.FSDataOutputStream;import org.apache.hadoop.fs.FileStatus;import org.apache.hadoop.fs.FileSystem;import org.apache.hadoop.fs.Path;import org.apache.hadoop.hdfs.DistributedFileSystem;import org.apache.hadoop.hdfs.protocol.DatanodeInfo;import org.apache.hadoop.io.IOUtils;import org.junit.Test;import hadoop.hdfs.utils.HDFSUtils;;/** * 通过FileSystem API 操作HDFS * */public class HDFSFsTest {    // 第一个:读取文件内容,就是text,cat方法    @Test    public void testRead() throws Exception {        // 获取文件系统        FileSystem hdfs = HDFSUtils.getFileSystem();        // 文件名称        Path path = new Path("/abc/aaa/touch.data");        // 打开文件输入流        FSDataInputStream in = hdfs.open(path);        // 读取文件内容到控制台显示        IOUtils.copyBytes(in, System.out, 4096, false);        // 关闭流        IOUtils.closeStream(in);    }    // 第二个:查看文件,相当于ls    @Test    public void testList() throws Exception {        FileSystem hdfs = HDFSUtils.getFileSystem();        // 目录        Path path = new Path("/");        FileStatus[] fileStatus = hdfs.listStatus(path);        for (FileStatus fs : fileStatus) {            Path p = fs.getPath();            String info = fs.isDir() ? "目录" : "文件";// 什么意思?            System.out.println(info + ":" + p);        }    }    // 第三个:创建目录。mkdir    @Test    public void testDirectory() throws Exception {        FileSystem hdfs = HDFSUtils.getFileSystem();        Path path = new Path("/abc/aaa/bbb/ccc");        boolean b = hdfs.mkdirs(path);// 相当于mkdir -p ,创建多级目录        System.out.println(b);    }    // 第四个:上传文件,put    @Test    public void testPut() throws Exception {        FileSystem hdfs = HDFSUtils.getFileSystem();        // 本地文件位置        Path localPath = new Path("E:/java_workspace/java0623/javaListFile.txt");        // hdfs文件上传路径        Path hdfsPath = new Path("/abc/aaa/bbb");        // 文件上传        hdfs.copyFromLocalFile(localPath, hdfsPath);    }    // 第五个:创建HDFS文件,并写入内容,create    @Test    public void testCreate() throws Exception {        FileSystem hdfs = HDFSUtils.getFileSystem();        // HDFS文件上传路径        Path path = new Path("/abc/aaa/bbb/ccc/ddd/d.txt");// 会创建路径中不存在的文件夹目录        // 创建文件,并获取输出流        FSDataOutputStream out = hdfs.create(path);        // 通过输出流的方法写入数据        out.write("woshiDDD".getBytes());        // out.writeUTF("你好,hadoop");//这个会出现乱码        IOUtils.closeStream(out);    }    // 第六个:对HDFS 上的文件进行改名,mv    @Test    public void testRename() throws Exception {        FileSystem hdfs = HDFSUtils.getFileSystem();        // HDFS文件上传路径        Path path = new Path("/abc/aaa/touch.data");        Path newPath = new Path("/abc/aaa/rename.data");        boolean isSuccess = hdfs.rename(path, newPath);        System.out.println(isSuccess);    }    // 第七个:删除HDFS上的文件,rm    @Test    public void testDelete() throws Exception {        FileSystem hdfs = HDFSUtils.getFileSystem();        Path path = new Path("/abc/aaa/bbb/a.txt");        boolean isSuccess = hdfs.deleteOnExit(path);        System.out.println(isSuccess);    }    // 第八个:删除HDFS的目录    @Test    public void testDelDir() throws Exception {        FileSystem hdfs = HDFSUtils.getFileSystem();        Path path = new Path("/abc/aaa/bbb/ccc/ddd");        boolean isSuccess = hdfs.delete(path, true);        System.out.println(isSuccess);    }    // 第九个:查找某个文件在HDFS集群上的位置    @Test    public void testLocation() throws Exception {        FileSystem hdfs = HDFSUtils.getFileSystem();        // HDFS文件上传路径        Path path = new Path("/abc/aaa/bbb/javaListFile.txt");        FileStatus fs = hdfs.getFileStatus(path);        BlockLocation[] bl = hdfs.getFileBlockLocations(fs, 0, fs.getLen());        for (BlockLocation blocklocation : bl) {            String[] hosts = blocklocation.getHosts();            for (String host : hosts) {                System.out.println(host);            }        }    }    // 第十个:获取HDFS上所有节点的名称信息    @Test    public void testCluster() throws Exception {        FileSystem hdfs = HDFSUtils.getFileSystem();        DistributedFileSystem dfs = (DistributedFileSystem)hdfs;        DatanodeInfo[] dataInfo = dfs.getDataNodeStats();        for(DatanodeInfo dataInfos : dataInfo){            String hostName = dataInfos.getHostName();            System.out.println(hostName);        }    }}
0 0
原创粉丝点击