文档章节

HDFS

八戒_o
 八戒_o
发布于 2016/02/15 17:18
字数 1657
阅读 248
收藏 4
点赞 1
评论 0

HDFS详解

http://my.oschina.net/crxy/blog/348868

hdfs工作原理

http://my.oschina.net/crxy/blog/385283

HDFS

HDFS适合做:

  1. 存储大文件。上G、T甚至P。

  2. 一次写入,多次读取。并且每次作业都要读取大部分的数据。

  3. 搭建在普通商业机群上就可以了。虽然会经常宕机,但HDFS有良好的容错机制。

HDFS不适合做:

  1. 实时数据获取。如果有这个需求可以用HBase。

  2. 很多小文件。因为namenode要存储HDFS的metadata(比如目录的树状结构,每个文件的文件名、ACL、长度、owner、文件内容存放的位置等等信息),所以HDFS上文件的数目受到namenode内存的限制。

  3. 并发环境下的写入和修改。

Block

一个磁盘的block通常是512B,内核一次读写磁盘不能少于这个数目。在HDFS上一个Block的默认大小是64M,HDFS block的大小可以通过ds.block.size来设置,很多工作站上把一个block调为128M。之所以要把block设置得这么大,是因为HDFS上的文件普遍都是大文件,如果block很小,那一个文件就要存放在很多block上,而这些位置信息都要被namenode所记录,一来浪费namenode的存储空间,二来检索一个文件的时候开销也比较高。

当一个文件的长度小于一个block size时,它会单独占用一个block,但它占用的磁盘空间仍然是其真实的长度。

Namenode和Datanode

namenode管理文件系统的namespace,而datanode负责存储和检索block。一般情况下一个block会存放在多个不同的datanode上,以提高容错性。datanode在读写HDFS文件时,都需要通过namenode来获知读写的具体位置。

你可以使用distcp命令在不同的datanode之间并行地复制大文件:

$ hadoop distcp hdfs://datanode1/foo hdfs://datanode2/bar

HDFS上的文件是使用URI来定位的,前缀都是hdfs://localhost:9000,你可以把这个前缀赋给属性fs.default.name(属性可以在配置文件中指定,也可以在代码中指定),这样你就不用每次都写这个前缀了,比如以下2个命令是等价的:

$ hadoop fs -ls /

$ hadoop fs -ls hsfs://localhost:9000/

本地文件系统的前缀是file://

复制代码

orisun@zcypc:~$ hadoop fs -ls file:///Found 22 items
drwxr-xr-x   - root root       4096 2012-08-02 19:17 /home
dr-xr-xr-x   - root root          0 2012-08-20 22:14 /proc
drwxr-xr-x   - root root       4096 2010-04-23 18:11 /mnt
drwx------   - root root       4096 2012-08-18 10:46 /root
drwxr-xr-x   - root root       4096 2012-08-18 10:40 /sbin
……

复制代码

HDFS默认的文件备份数量是3,这个可以在dfs.replication属性中设置,在伪分布式模式中由于datanode只有一个,所以要把该值设为1。当你使用hadoop fs -ls命令时会得到形如:

drwxr-xr-x     -   orisun   supergroup        0   2012-08-20 14:23   /tmp

-rw-------    1   orisun   supergroup   4   2012-08-20 14:23   /tmp/jobtracker.info

跟UNIX下的ls命令很像,其中第2列就是replication的数目,第5列是文件的长度,以B为单位(文件夹的长度是0,而在UNIX文件系统中目录的长度是512B的整倍数,因为目录所占的空间是以块为分配单位的,每块为512B)。

FSDataInputStream继承自Java的DataInputStream并支持随机读写。

public class FSDataInputStream extends DataInputStream implements Seekable, PositionedReadable {}
public interface Seekable {
  void seek(long pos) throws IOException;
  long getPos() throws IOException;
  boolean seekToNewSource(long targetPos) throws IOException;
}

FSDataInputStream还可以从指定的位置读取文件的一部分。

public interface PositionedReadable {    public int read(long position, byte[] buffer, int offset, int length) throws IOException;    public void readFully(long position, byte[] buffer, int offset, int length) throws IOException;    public void readFully(long position, byte[] buffer) throws IOException;
}

如果你想在HDFS上新建一文件可以使用

public FSDataOutputStream create(Path f) throws IOException

使用create()函数时注意2点:文件必须之前不存在;它可附带地创建任意多级的父目录。

有时候你可能会需要用append(),在文件不存在时会创建它。

public FSDataOutputStream append(Path f) throws IOException

重命名文件

public void rename(String oldName,String newName)

当然你也可以用mkdir来创建目录

public boolean mkdirs(Path f) throws IOException

由于create()可以附带地创建任意多级的父目录,所以mkdir你并不会常用。

FileSystem的getFileStatus()方法可以获取文件和目录的FileStatus。

Path file = new Path("/dir/file");
FileStatus stat = fs.getFileStatus(file);

然后你就可以访问:

复制代码

stat.getPath()
stat.getLen()
stat.isLen()
stat.getMogificationTime()
stat.getReplication()
stat.getBlockSize()
stat.getOwner()
stat.getReplication()
stat.getBlockSize()
stat.getGroup()
stat.getPermission()

复制代码

实际上上述信息都存储在namenode中。

你还可以获取一个目录下所有文件的FileStatus。

public FileStatus[] listStatus(Path f) throws IOExceptionpublic FileStatus[] listStatus(Path f, PathFilter filter) throws IOExceptionpublic FileStatus[] listStatus(Path[] files) throws IOExceptionpublic FileStatus[] listStatus(Path[] files, PathFilter filter) throws IOException

在指定文件时,hadoop同样支持globbing,它支持的wildcard有:

*  0个或多个任意字符

?  任意单个字符

[ab]  [^ab]  [a-b]  [^a-b]

{exp1,exp2}    匹配exp1或exp2

\c  转义

fs.listStatus(new Path("/2007/*/*"), new RegexExcludeFilter("^.*/2007/12/31$"))

将匹配2007年的所有文件,但是2007-12-31的文件将被filter掉。

public boolean delete(Path f, boolean recursive) throws IOException

删除目录时可以选择是否启用递归模式。

 上面已经提到大量的小文件会极大消耗namenode的内存,所以在这种情况下我们需要使用Hadoop Archives(HAR)把文件归档为一个大文件。

$ hadoop archive -archiveName orisun.har -p /user/orisun /user

把/user/orisun下的所有文件打包成orisun.tar放在/user目录下。

你还可以查看一个har文件中包含哪些文件:

复制代码

orisun@zcypc:~$ hadoop fs -lsr har:///user/orisun.hardrwxr-xr-x   - orisun supergroup          0 2012-08-20 16:49 /user/orisun.har/mse-rw-r--r--   1 orisun supergroup          0 2012-08-20 16:49 /user/orisun.har/mse/list-rw-r--r--   1 orisun supergroup          0 2012-08-20 16:49 /user/orisun.har/book
orisun@zcypc:~$ hadoop fs -ls har:///user/orisun.har/mseFound 1 items-rw-r--r--   1 orisun supergroup          0 2012-08-20 16:49 /user/orisun.har/mse/list

复制代码

HAR也是一个文件系统,一个Har URI的完整模式是har://<scheme>-<host>/<path>

orisun@zcypc:~$ hadoop fs -lsr har://hdfs-localhost:9000/user/orisun.har/mse-rw-r--r--   1 orisun supergroup          0 2012-08-20 16:49 /user/orisun.har/mse/list

删除har文件必须使用rmr命令,用rm是不行的。

$ hadoop fs -rmr /user/orisun.har

 使用HAR的一些限制:

  1. 会产生原始文件的完整备份,占用磁盘空间。当然你可以以在建好har文件后把原文件删掉。

  2. HAR只是把多个文件打包成一个文件并没有采用任何的压缩策略。

  3. HAR文件是不可变,如何你想增加或从har中删除一个文件,你只能重新归档。

  4. InputFormat不理会har的存在,这意味着har文件对于MapReduce来说仍然会产生多个InputSlit,不会提高效率。要解决“小文件很多导致map task很多”的问题,可以采用CombineFileInputFormat。


© 著作权归作者所有

共有 人打赏支持
八戒_o
粉丝 22
博文 123
码字总数 43412
作品 0
成都
程序员

暂无相关文章

Linux kernel脉络和主干总结

写在前面 前人常说,对Linux操作系统/内核的理解,是计算机行业从业者的内功,决定了你在技术领域想走多远。但内核的庞大以及学习曲线之陡峭,总让我在学习途中觉得犹如“管中窥豹”。 随着工...

Markz0928 ⋅ 17分钟前 ⋅ 0

在gcc中使用intel风格的内联汇编

很简单,内联汇编使用asm(“.intel_syntax noprefix/n”)声明一下,以后的内联汇编就可以用intel风格了,构建可执行文件时给gcc加上-masm=intel参数。 先写一个小程序测试一下: [cpp] view...

simpower ⋅ 27分钟前 ⋅ 0

NIO 之 ByteBuffer实现原理

相关文章 BIO、NIO、AIO 内部原理分析 NIO 之 Selector实现原理 NIO 之 Channel实现原理 前言 Java NIO 主要由下面3部分组成: Buffer Channel Selector 在传统IO中,流是基于字节的方式进行...

轨迹_ ⋅ 36分钟前 ⋅ 0

Jenkins docker权限问题

环境Ubuntu Server 工具 jenkins-war:2.89.2 报错信息 Cannot connect to the Docker daemon. Is the docker daemon running on this host?Build step 'Execute shell' marked build as fai......

Pulsar-V ⋅ 37分钟前 ⋅ 0

180621-一个简单的时间窗口设计与实现

如何设计一个计数的时间窗口 时间窗口,通常对于一些实时信息展示中用得比较多,比如维持一个五分钟的交易明细时间窗口,就需要记录当前时间,到五分钟之前的所有交易明细,而五分钟之前的数...

小灰灰Blog ⋅ 59分钟前 ⋅ 0

Android之Dalvik、ART、JIT、AOT

Android之Dalvik、ART、JIT、AOT 本文内容:Dalvik、ART、JIT、AOT之间关系 本文定位:知识记录 学习过程记录,加深理解,提升文字组合表达能力。也希望能给学习的同学一些灵感 本文整理于[...

lichuangnk ⋅ 今天 ⋅ 0

Thrift RPC实战(五) thrift连接池

Thrift本身没有提供连接池,我们可以用Apache Commons Pool2来实现一个 一、定义对象工厂 BasePooledObjectFactory<T> extends BaseObject implements PooledObjectFactory<T> public class......

lemonLove ⋅ 今天 ⋅ 0

git 命令简写

简写 命令 g git gst git status gd git diff gdc git diff --cached gdv git diff -w "$@" | view - gl git pull gup git pull --rebase gp git push gc git commit -v gc! git commit -v ......

charley158 ⋅ 今天 ⋅ 0

Java中的锁使用与实现

1.Lock接口 锁是用来控制多个线程访问共享资源的方式,一般来说,一个锁能够防止多个线程同时访问共享资源。 在Lock出现之前,java程序是靠synchronized关键字实现锁功能的,而Java SE5之后,...

ZH-JSON ⋅ 今天 ⋅ 0

Intellij IDEA神器常用技巧四-类和方法注释模板设置

IDEA自带的注释模板不是太好用,我本人到网上搜集了很多资料系统的整理了一下制作了一份比较完整的模板来分享给大家,我不是专业玩博客的,写这篇文章只是为了让大家省事。 这里设置的注释模...

Mkeeper ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部