hadoop之HDFS

前言

学习HDFS文件系统

分布式文件系统

  • 数据量很多,一台机器放不下,需要多台机器共同存储
  • 允许文件通过网络在多台主机上分享
  • 通透性,对于用户来说,使用存储和普通单机没什么区别
  • 容错,某些机器挂了,对系统没有影响

hadoop文件系统

  • 对Linux文件系统的抽象。抽象类为org.apache.hadoop.fs.FileSystem,HDFS只是一个实例
  • 丰富的Shell命令
  • 提供JAVA API编程接口

hadoop_004

HDFS

  • 主从结构,通过心跳机制维持
  • NameNode是master,DataNode是slave
  • 处理超大文件
  • 机器不要很好的性能
  • 不适合处理小文件
  • 不适合任意修改文件

命令行(整体设计与Linux命令行相似)

列出所有文件

1
hadoop fs -ls /

本地文件上传到hdfs

1
2
hadoop fs -copyFromLocal /root/xxx hdfs:/hadoop01:9000/xxx
hadoop fs -put /root/xxx hdfs:/hadoop01:9000/xxx

下载文件,是否加校验和

1
2
hadoop fs -copyToLocal [-ignorecrc] [-crc] /root/xxx hdfs:/hadoop01:9000/xxx
hadoop fs -get [-ignorecrc] [-crc] /root/xxx hdfs:/hadoop01:9000/xxx

删除文件,文件夹多加-r参数

1
hadoop fs -rm hdfs://hadoop01:9000/wc_test_01

Java API

  • Configuration类,封装了所有的配置
  • FileSystem类,是个抽象类,DistributedFileSystem是它的实现之一
  • FSDataInputStream和FSDataOutputStream是HDFS的输入和输出流,分别通过FileSystem的open方法和create方法获得

如何从HDFS读数据?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class FileSystemCat {
public static void main(String[] args) throws IOException {
String url = "hdfs://hadoop01:9000/wc_test_01";
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(URI.create(url), conf);
InputStream in = null;
try {
in = fs.open(new Path(url));
IOUtils.copyBytes(in, System.out, 4 * 1024, false);
} finally {
IOUtils.closeStream(in);
}
}
}

文件内容将打印在控制台上

如何从HDFS写数据?

1
2
3
4
5
6
7
8
9
10
11
12
13
public class FileCopy {
public static void main(String[] args) throws Exception {
String local = "D:/1.txt";
String dst = "hdfs://hadoop01:9000/1.txt";
// String local = args[0];
// String dst = args[1];
InputStream in = new BufferedInputStream(new FileInputStream(local));
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(URI.create(dst), conf, "root");
OutputStream out = fs.create(new Path(dst));
IOUtils.copyBytes(in, out, 4 * 1024, true);
}
}

不能直接上传Windows的文件,权限不够;但可以伪装成root用户,这样就可以上传

如何创建目录

这个方法会创建不存在的父目录

1
public boolen mkdirs(Path f) throws IOException

如何查询文件系统

查询元数据和目录结构

1
FileStatus getFileStatus( Path f) throws IOException

FileSystem的listStatus提供了列出文件目录内容的方法

1
2
3
4
FileStatus[] listStatus( Path f) throws IOException
FileStatus[] listStatus( Path f, PathFilter filter) throws IOException
FileStatus[] listStatus( Path[] files) throws IOException
FileStatus[] listStatus( Path[] files, PathFilter filter) throws IOException

显示文件元数据信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class ShowFileStatus {
public static void main(String[] args) throws Exception {
String url = "hdfs://hadoop01:9000/wc_test_01";
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(new URI(url), conf);
Path path = new Path(url);
FileStatus stat = fs.getFileStatus(path);
System.out.println("Full path:" + stat.getPath().toUri().getPath());
if (stat.isDirectory()) {
System.out.println("is dir");
} else {
System.out.println("is file");
}
System.out.println("Length:" + stat.getLen());
System.out.println("Last modified time:" + stat.getModificationTime());
System.out.println("Replication:" + stat.getReplication());
System.out.println("Block size:" + stat.getBlockSize());
System.out.println("Owner:" + stat.getOwner());
System.out.println("Group:" + stat.getGroup());
System.out.println("Permission:" + stat.getPermission());
}
}

列出目录内容

1
2
3
4
5
6
7
8
9
10
11
12
13
public class ListStatus {
public static void main(String[] args) throws Exception {
String url = "hdfs://hadoop01:9000/tmp";
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(new URI(url), conf, "root");
Path path = new Path(url);
FileStatus[] statuses = fs.listStatus(path);
Path[] paths = FileUtil.stat2Paths(statuses);
for (Path p : paths) {
System.out.println(p);
}
}
}

利用通配符来实现文件的筛选

利用*或者?来匹配文件

1
2
FileStatus[] globStatus( Path pathPattern) throws IOException
FileStatus[] globStatus( Path pathPattern, PathFilter filter) throws IOException

利用正则式来筛选文件

实现接口

1
2
3
public interface PathFilter{
boolean accept(Path path); //如果接受该path,则返回true
}

HDFS写文件原理

原理图如下

hadoop_005

HDFS读文件原理

原理图如下

hadoop_006

原理过程先放着,以后再看..

网络距离

就是两个节点的物理距离。当文件需要拷贝时,距离近的节点优先,以提高性能

HDFS一致性模型

HDFS提供了一个同步函数,这个方法是FSDataOutputStream类的sync()函数。当sync()函数返回成功时,HDFS就可以保证此时写入的文件数据文件是一致的并且对于所有用户是可见的。关闭一个文件时也隐式执行了sync()函数

HDFS文件系统结构

HDFS文件镜像和编辑日志

  • 通常情况下,辅助namenode每隔一个小时(通过fs.checkpoint.period属性设置,以秒为单位)创建检查点
  • 当编辑日志大小达到64MB(由fs.checkpoint.size属性设置,以字节为单位)创建检查点。系统每隔五分钟检查一次编辑日志大小

用于误操作的恢复,和文件系统的备份

归档文件(Archive)

HDFS不利于小文件的存储,浪费性能。可以将小文件打包成大文件存储

1
hadoop archive -archiveName files.har 1.txt 2.txt 3.txt