Hadoop权威指南 第三章笔记

1.

HDFS以流式数据访问模式来存储超大文件。要求低时间延迟数据访问的应用不适合hdfs。hdfs是为搞数据吞吐量应用优化的,这可能会议高时间延迟为代价。对于低延迟的访问需求,HBase是更好的选择。由于namenode将文件系统的元数据存储在内存中,因此该文件系统所能存储的文件总数受限于namenode的内存容量。hdfs不支持具有多个写入者的操作,也不支持在文件的任意位置进行修改。

2.

每个磁盘都有默认的数据块大小,这是磁盘进行数据读/写的最小单位。HDFS中小于一个块大小的文件不会占据整个块的空间。HDFS中fsck指令可以显示块的信息。

执行以下命令,将列出文件系统中各个文件由那些块构成:

hadoop fsck / -files -blocks

3.

HDFS集群有两类结点,并以管理者——工作者模式运行,即一个namenode(管理者)和多个datanode(工作者)。namenode管理文件系统的命名空间。它维护着文件系统树及整棵树内的所有的文件和目录。这些信息以两个文件形式永久保存在本地磁盘上:命名空间镜像文件和编辑日志文件。namenode也记录着每个文件中各个块所在数据结点信息,但它并不永久保存块的位置信息,因为这些信息会在启动时由数据结点创建。

client代表用户通过namenode和datanode交互来访问整个文件系统。

datanode是文件系统的工作结点。它们根据需要存储并检索数据块(受客户端或namenode调度),并且定期向namenode发送它们所存储的块的列表。

没有namenode,文件系统将无法使用。因为我们不知道如何根据datanode的块来重建文件。Hadoop提供了两种namenode的容错机制。

第一种机制是备份那些组成文件系统元数据持久状态的文件。Hadoop可以通过配置namenode在多个文件系统在保存元数据的持久状态。

第二种机制是运行一个辅助namenode,但它不能被用作namenode。这个辅助namenode的重要作用是定期通过编辑日志合并命名空间镜像,以防止编辑日志过大。


4.

伪分布配置时第一项是fs.default.name,设置为hdfs://localhost/,用于设置Hadoop的默认文件系统,文件系统由url指定的。hdfs的守护进程将通过该属性来确定hdfs的namenode的主机及端口。我们将在localhost的端口8020上运行namenode。这样一来,hadoop客户端可以通过该属性得知namenode在哪里运行进而连接得到它。

第二个属性dfs.reolication,我们设为1,这样一来,hdfs就不会按默认设置将文件系统块副本设为3.在单独一个datanode上运行时,hdfs无法将块复制到3个datanode上,因此它会持续给出块复本不足的警告。设置这个属性后,就不会再有问题了。

5.

第2列是这个文件的备份数。由于我们在整个文件系统范围内设置的默认复本数为1,所以这里显示的也都是1。因为本例中没有使用复本的概念——目录作为元数据保存在namenode中,而非datanode中。


6.Hadoop文件系统通过Hadoop Path对象来代表文件(而非java.io.File对象)

获取FileSystem实例有两种静态工厂方法:

public  static FileSystem get(Configuration conf) throws IOException

public static FileSystem get(URI uri, Configuration conf) throws IOException

Configuration对象封装了客户端或服务器的配置,通过设置配置文件读取类路径来实现(如conf/core-site.xml).

有了FileSystem实例后,我们调用open()函数来获取文件的输入流:

public FSDataInputStream open(Path f) throws IOException

public abstract FSDataInputStream(Path f, int buffersize) throws IOException 

第一个方法默认使用的缓冲区大小4KB。


实际上FileSystem对象中的open方法返回的是FSDataInputStream对象,而不是标准的java.io对象。这个类是继承了java.io.DataInputStram接口的一个特殊类。

FSDataInputStream类也实现了PositionedReadable接口,从一个指定偏移量处读取文件的一部分:

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;
}

read()方法从文件的指定position处读取至多为length字节的数据并存入缓冲区buffer的指定偏离量offser处。返回值是实际读到的字节数。


FileSystem实例的create()方法返回FSDataOutputStream对象,与FSDataInputStream类相似,它也有一个查询文件当前位置的方法。


FileSystem实例提供了创建目录的方法。

public boolean mkdirs(Path f) throws IOException.

通常不需要显示创建一个目录,因为调用create()方法写入文件时会自动创建父目录。


FileStatus类封装了文件系统中文件和目录的元数据,包括文件长度、块大小、备份、修改时间、所有者以及权限信息。

FileSystem的getFileStatus()方法用于获取文件或目录的FileStatus对象。


7.

客户端通过调用FileSyste对象的open()方法来打开希望读取的文件。DistributedFileSystem通过RPC来调用namenode,以确定文件起始块的位置。对于每一个块,namenode返回该块副本的datanode地址。DistributedFileSystem类返回一个FSDataInputStream对象(一个支持文件定位的输入流)给客户端并读取数据。FSDataInputStream类转而封装DFSInputStream对象,该对象管理着datanode和namenode的I/O。接着,客户端对这个输入流调用read()方法。存储着文件起始块的datanode地址的DFSInputStream随即连接距离最近的Datanode。通过对数据流反复调用read()方法,可以将数据从datanode传输到客户端。到达块的末端时,DFSInputStream会关闭该datanode的连接,然后寻找下一个块的最佳datanode。客户端只需要读取连续的流,并且对于客户端都是透明的。


客户端从流中读取数据时,块是按照打开DFSInputStream与datanode新建连接的顺序读取的。它也需要读取namenode来检索下一批所需块的datanode的位置。一旦客户端完成读取,就对FSDataInputStream调用close()方法。

在读取数据的时候,如果DFSInputStream在与datanode通信时遇到错误,它便会尝试从这个块的另外一个最邻近的datanode读取数据。

重点是:namenode告知客户端每个块最佳的datanode,并让客户端直接联系该datanode并检索数据。namenode仅需要响应快位置的请求而无需响应数据请求。


8.

在客户端写入数据时,DFSOutputStream将它分成一个个数据包,并写入内部队列,称为数据队列。DataStreamer处理数据队列,它的任务是根据datanode列表来要求namenode分配合适的新块来存储数据备份。DFSOutputStream也维护着一个内部数据包队列来等待datanode的收到确认回执,称为确认队列。当收到管道中所有datanode确认信息后,该数据包才会从确认队列删除。

如果在数据写入期间,datanode发生故障。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值