Hadoop文件系统HDFS

Hadoop三大核心设计

MapReduce Map:任务分解 Reduce:结果汇总

HDFS NameNode:管理里文件元数据 DataNode:存储物理文件 Client:获取文件的各种API

Hbase 列式内存数据库

 

 

HDFS的体系结构

NameNode:即元数据节点,用来管理文件系统的命名空间,记录每个文件数据在各个DataNode上的位置和副本信息,协调客户端对文件的访问。

元数据文件:VERSION、seen_txid、fsimage_*、fsimage_*.md5、edits_*

 

DataNode:即数据节点用来存储数据,负责所在物理节点的存储管理,一次写入,多次读取(不修改),文件由数据块组成,典型的块大小是64MB,数据块尽量散布到各个节点。

 

SecondaryNameNode:NameNode的一个快照,周期性的备份namenode,记录namenode中的metadata及其他数据,可以用来恢复Namenode

 

dfs.namenode.name.dir/current/文件夹的几个文件:

VERSION:存放的是版本信息,文件系统的标示符

seen_txid:存放事务ID的文件,它里面的数字要与edits的尾数一致,也就是与edits_inprogress_000000000*后边的数字一致,inprogress是正在使用的edits文件

fsimage_*、fsimage_*.md5、edits_*:存放的是文件的元数据信息。

 

HDFS文件读取的过程如下:

1).使用HDFS提供的客户端开发库Client,向远程的Namenode发起RPC请求;

2).Namenode会视情况返回文件的部分或者全部block列表,对于每个block,Namenode都会返回有该block拷贝的DataNode地址;

3).客户端开发库Client会选取离客户端最接近的DataNode来读取block;如果客户端本身就是DataNode,那么将从本地直接获取数据.

4).读取完当前block的数据后,关闭与当前的DataNode连接,并为读取下一个block寻找最佳的DataNode;

5).当读完列表的block后,且文件读取还没有结束,客户端开发库会继续向Namenode获取下一批的block列表。

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

 

HDFS写入文件的过程:

1).使用HDFS提供的客户端开发库Client,向远程的Namenode发起RPC请求;

2).Namenode会检查要创建的文件是否已经存在,创建者是否有权限进行操作,成功则会为文件创建一个记录,否则会让客户端抛出异常;

4).当客户端开始写入文件的时候,开发库会将文件切分成多个packets,并在内部以数据队列"data queue"的形式管理这些packets,并向Namenode申请新的blocks,获取用来存储replicas的合适的datanodes列表,列表的大小根据在Namenode中对replication的设置而定。

开始以pipeline(管道)的形式将packet写入所有的replicas中。开发库把packet以流的方式写入第一个datanode,该datanode把该packet存储之后,再将其传递给在此pipeline中的下一个datanode,直到最后一个datanode,这种写数据的方式呈流水线的形式。

5).最后一个datanode成功存储之后会返回一个ack packet,在pipeline里传递至客户端,在客户端的开发库内部维护着"ack queue",成功收到datanode返回的ack packet后会从"ack queue"移除相应的packet。

6).如果传输过程中,有某个datanode出现了故障,那么当前的pipeline会被关闭,出现故障的datanode会从当前的pipeline中移除,剩余的block会继续剩下的datanode中继续以pipeline的形式传输,同时Namenode会分配一个新的datanode,保持replicas设定的数量。

 

 

HDFS的shell操作

直接访问Hadoop程序

在/etc/prifile中加入

export HADOOP_HOME=/home/hduser/hadoop (hadoop的安装目录)

export PATH=$HADOOP_HOME/bin:$PATH

 

HDFS命令格式:

HDFS基本命令(在hadoop目录下执行为例)

bin/hadoop fs -cmd <args>

cmd:具体的操作,基本上与UNIX的命令行相同

<args>:有时需包含参数

例如:bin/hadoopfs -ls /

 

mkdir 使用方法:hadoop fs -mkdir <paths>

示例:hadoop fs-mkdir /user

 

ls 列出path目录下的内容,包括文件名,权限,所有者,大小和修改时间

hadoop fs -ls /

hadoop fs -ls -R /

 

put 使用方法:hadoop fs -put <localsrc> ... <dst>

从本地文件系统中复制单个或多个源路径到目标文件系统。也支持从标准输入中读取输入写入目标文件系统。

hadoop fs -put localfile /user/ 拷贝localfile文件到hdfs的user目录下

hadoop fs -put localfile1 localfile2 /user/同时拷贝localfile1和localfile2文件到hdfs的user目录下

hadoop fs -put - /user/hadoopfile 在hadoopfile文件里手工录入内容(录入之前hadoopfile文件不存在),按Ctrl+C键录入结束

hadoop fs -ls /user/hadoopfile 查看文件内容

hadoop fs -ls /user/read.txt 删除文件

 

get 使用方法:hadoop fs -get [-ignorecrc] [-crc]

<src> <localdst> 复制文件到本地文件系统

示例:hadoop fs-get /user/hadoop/file localfile

 

cat 使用方法:hadoop fs -cat URI [URI ...]

示例:hadoop fs-cat /user/hadoop/file

 

rm 使用方法:hadoop fs -rm URI [URI ...]

删除指定的文件。只删除非空目录和文件。请参考rmr命令了解递归删除。

示例:hadoop fs-rm /emptydir

 

rmr 使用方法:hadoop fs -rmr URI [URI ...]

delete的递归版本。

示例:hadoop fs-rm -r /user/hadoop/dir

 

getmerge 使用方法:hadoop fs -getmerge <src> <localdst> [addnl]

接受一个源目录和一个目标文件作为输入,并且将源目录中所有的文件连接成本地目标文件。addnl是可选的,用于指定在每个文件结尾添加一个换行符。

示例:hadoop fs-getmerge /input2 file2.txt

 

mv 使用方法:hadoop fs -mv URI [URI ...] <dest>

将文件从源路径移动到目标路径。这个命令允许有多个源路径,此时目标路径必须是一个目录。

不允许在不同的文件系统间移动文件。

示例:hadoop fs-mv /hadoop/file1 /hadoop/file2

 

stat 使用方法:hadoop fs -stat URI [URI ...]

返回指定路径的统计信息。

示例:hadoop fs-stat /input2

 

tail 使用方法:hadoop fs -tail [-f] URI

将文件尾部1k字节的呢绒输出到stdout。支持-f选项,行为和Unix中一致。

示例:hadoop fs-tail pathname

 

chmod 使用方法:hadoop fs -chmod [-R] <MODE[,MODE]... | OCTALMODE> URI [URI...]

设为所有人皆可读取

chmod a+r file1.txt

 

chown 使用方法:hadoop fs -chown [-R] [OWNER][:[GROUP]] URI [URI]

 

touchz 使用方法:hadoop fs -touchz URI [URI ...]

创建一个0字节的空文件。

示例:hadoop fs-touchz pathname

 

copyToLocal 使用方法:hadoop fs -copyToLocal [ignorecrc] [-crc] URI <localdst>

除了限定目标路径是一个本地文件外,和get命令类似。

 

copyFromLocal 使用方法:hadoop fs -copyFromLocal<localsrc> URI

除了限定源路径是一个本地文件外,和put命令相似。

 

cp 使用方法:hadoop fs -cp URI [URI ...] <dest>

将文件从源路径复制到目标路径。这个命令允许有多个源路径,此时目标路径必须是一个目录。

hadoop fs -cp /user/hadoop/file1/user/hadoop/file2

 

du 使用方法:hadoop fs -du URI [URI ...]

显示目录中所有文件的大小

示例:hadoop fs-du /user/hadoop/dir1

 

du -s 使用方法:hadoop fs -du -s <args>

显示文件的大小

 

expunge 使用方法:hadoop fs -expunge

清空回收站

 

Hadoop的命令解析:

put命令只能从本地的文件复制到HDFS上;get命令将HDFS上的文件复制到本地;cp命令只能在相同的文件系统上互相复制文件。这三个命令都可以复制多个文件。复制单个文件时,目标路径可以是目录也可以是文件,目标路径是目录时,文件名不改变,目标路径是文件时,可以修改文件名;复制多个文件时,目标路径必须是目录,文件名不能修改。

copyFromLocal命令,此命令与put命令相似,区别是此命令只能复制一个文件。目标路径是目录时,文件名不改变,目标路径是文件时,可以修改文件名。

copyToLocal命令,此命令与get命令相似,区别是此命令只能复制一个文件。目标路径是目录时,文件名不改变,目标路径是文件时,可以修改文件名。

mv命令只能在相同的文件系统上移动文件,可以移动多个文件。标路径是目录时,文件名不改变,目标路径是文件时,可以修改文件名。

以上所有目录必须是存在的。

 

HDFS的API方式访问

Configuration类:该类的对象封装了客户端或者服务端的配置。

FileSystem类:该类的对象是一个文件系统对象,可以用该队想的一些方法来对文件进行操作。

FSDataInputStream和FSDataOutputStream:这两个类是HDFS中的输入输出流。

 

基本流程:

得到Configuration对象

得到FileSystem对象

进行文件操作(读写、删除、改名)

 

所需引入的库

importorg.apache.hadoop.conf.Configuration;

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.io.IOUtils;

 

文件操作前的准备工作

获取配置信息

Configuration conf = new Configuration();

建立文件系统对象

FileSystem fs = FileSystem.get(conf);

 

写文件

Path dstPath = new Path(dst);//目标路径

FSDataOutputStream outputStream =fs.create(dstPath);//打开一个输出流

outputStream.write(contents);

outputStream.close();

fs.close();

 

读文件

InputStream in = null;

in = fs.open(srcPath);

IOUtils.copyBytes(in,System.out,4096,false);//复制到标准输出流

IOUtils.closeStream(in);

 

上传文件到HDFS

Path srcPath = new Path(src);//原路径

Path dstPath = new Path(dst);//目标路径

fs.copyFromLocalFile(false,srcPath,dstPath);

前面参数是指是否删除原文件,true为删除,默认为false

 

获取指定文件信息

FileStatus[] fileStatus =fs.listStatus(dstPath);

boolean isok=fs.rename(oldPath,newPath);

boolean isok=fs.deleteOnExit(path);

boolean isok=fs.mkdirs(srcPath);

 

 

 

(Eclipse开发环境的建立请看参考文档)

 

 

HDFS API具体操作:

 

打开eclipse建立一个工程,将代码copy,逐步运行。

在工程中建立一个conf目录,注意先将相关的配置文件拷贝过去主要是三个文件core-site.xml ,mapred-site.xml,hdfs-site.xml

并在project属性中设置java build path 单击addfolder将conf目录加上

import java.io.FileInputStream;

import java.io.IOException;

import java.io.InputStream;

importorg.apache.hadoop.conf.Configuration;

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.io.IOUtils;

 

public class HdfsFile {

   

   //创建新文件

   public static void createFile(String dst , byte[] contents) throwsIOException{

       Configuration conf = new Configuration();

       FileSystem fs = FileSystem.get(conf);

       Path dstPath = new Path(dst); //目标路径

       //打开一个输出流

       FSDataOutputStream outputStream = fs.create(dstPath);

       outputStream.write(contents);

       outputStream.close();

       fs.close();

       System.out.println("文件创建成功!");

    }

   

   //上传本地文件

   public static void uploadFile(String src,String dst) throws IOException{

       Configuration conf = new Configuration();

       FileSystem fs = FileSystem.get(conf);

       Path srcPath = new Path(src); //原路径

       Path dstPath = new Path(dst); //目标路径

       //调用文件系统的文件复制函数,前面参数是指是否删除原文件,true为删除,默认为false

       fs.copyFromLocalFile(false,srcPath, dstPath);

       

       //打印文件路径

       System.out.println("Upload to"+conf.get("fs.default.name"));

       System.out.println("------------listfiles------------"+"\n");

       FileStatus [] fileStatus = fs.listStatus(dstPath);

       for (FileStatus file : fileStatus)

       {

           System.out.println(file.getPath());

       }

       fs.close();

    }

   

   //文件重命名

   public static void rename(String oldName,String newName) throwsIOException{

       Configuration conf = new Configuration();

       FileSystem fs = FileSystem.get(conf);

       Path oldPath = new Path(oldName);

       Path newPath = new Path(newName);

       boolean isok = fs.rename(oldPath, newPath);

       if(isok){

           System.out.println("rename ok!");

       }else{

           System.out.println("rename failure");

       }

       fs.close();

    }

   //删除文件

   public static void delete(String filePath) throws IOException{

       Configuration conf = new Configuration();

       FileSystem fs = FileSystem.get(conf);

       Path path = new Path(filePath);

       boolean isok = fs.deleteOnExit(path);

       if(isok){

           System.out.println("delete ok!");

       }else{

           System.out.println("delete failure");

       }

       fs.close();

    }

   

   //创建目录

   public static void mkdir(String path) throws IOException{

       Configuration conf = new Configuration();

       FileSystem fs = FileSystem.get(conf);

       Path srcPath = new Path(path);

       boolean isok = fs.mkdirs(srcPath);

       if(isok){

           System.out.println("create dir ok!");

       }else{

           System.out.println("create dir failure");

       }

       fs.close();

    }

   

   //读取文件的内容

   public static void readFile(String filePath) throws IOException{

       Configuration conf = new Configuration();

       FileSystem fs = FileSystem.get(conf);

       Path srcPath = new Path(filePath);

       InputStream in = null;

       try {

           in = fs.open(srcPath);

           IOUtils.copyBytes(in, System.out, 4096, false); //复制到标准输出流

       } finally {

           IOUtils.closeStream(in);

       }

    }

   

   

   public static void main(String[] args) throws IOException {

       //测试上传文件

       //uploadFile("/home/hadoop/music1.txt","hdfs://master:9000/user/hadoop/test.txt");

       //测试创建文件

      //byte[] contents =  "hello world 世界你好\n".getBytes();

      //createFile("hdfs://master:9000/user/hadoop/test1/d.txt",contents);

       //测试重命名

       //rename("hdfs://master:9000/user/hadoop/test1/d.txt","hdfs://master:9000/user/hadoop/test1/dd.txt");

       //测试删除文件

       //delete("hdfs://master:9000/user/hadoop/test1/d.txt"); //使用相对路径

      //delete("hdfs://master:9000/user/hadoop/test1");    //删除目录

       //测试新建目录

      // mkdir("hdfs://master:9000/user/hadoop/test1");

       //测试读取文件

        //readFile("hdfs://master:9000/user/hadoop/test1/d.txt");

    }

 

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值