hadoop笔记-hdfs文件读写

概念

文件系统

磁盘进行读写的最小单位:数据块,文件系统构建于磁盘之上,文件系统的块大小是磁盘块的整数倍。前端

文件系统块通常为几千字节,磁盘块通常512字节。node

hdfs的block、pocket、chunk

  • block面试

 hdfs的块,常说的block,是这三个里最大的单位。默认128MB(配置参数:dfs.block.size)网络

128MB的缘由:块过小会增长寻址时间;块太大会减小Map的任务(一般一个Map只处理一个块的数据)。并发

注:文件的大小小于一个block并不会占据整个block的空间,如一个1M的文件存储在128MB的block中时,并非占用128MB的的磁盘空间,而是1MB。异步

  • pocket分布式

这三个里面中等大小的单位,DFSClient流向DataNode的粒度,以dfs.write.packet.size参数为参考值,默认是64K;注:这个参数为参考值,是指真正在进行数据传输时,会以它为基准进行调整,调整的缘由是一个packet有特定的结构,调整的目标是这个packet的大小恰好包含结构中的全部成员,同时也保证写到DataNode后当前block的大小不超过设定值;oop

  • chunkspa

是最小的一个单位,它是DFSClient到DataNode数据传输中进行数据校验的粒度,由io.bytes.per.checksum参数决定,默认是512B;事实上一个chunk还包含4B的校验值,于是chunk写入packet时是516B;数据与检验值的比值为128:1,因此对于一个128M的block会有一个1M的校验文件与之对应;设计

分布式文件系统使用块的好处

  1. 一个文件的大小能够大于网络中任意磁盘的容量。
  2. 使用抽象快而不是整个文件做为存储,大大简化了存储子系统的设计。

文件读

  1.  客户端调用FileSyste对象的open()方法打开要读取的文件。
  2. DistractedFileSystem经过远程过程调用(RPC)来调用namenode,以获取文件的其实位置。对于每个块,namenode返回该副本的datanode的地址。这些datanode根据它们与客户端的距离来排序(根据集群的网络拓扑)。若是客户端自己就是一个datanode,那么会从保存相应数据块副本的本地datanode读取数据。
  3. DistrubutedFileSystem返回一个FSDataInputStream对象(支持文件定位的数据流)给客户端便读取数据。FSDataInputStream转而封装DFSInputStream对象,它管理datanode和namenode的I/O。接着客户端对这个数据流调用read()。
  4. 存储着文件的块的datanode地址的DFSInputStream会链接距离最近的文件中第一个块所在的datanode。反复调用read()将数据从datanode传输到客户端。
  5. 读到块的末尾时,DFSInputStream关闭与前一个datanode的链接,而后寻找下一个块的最佳datanode。
  6. 客户端的读写顺序时按打开的datanode的顺序读的,一旦读取完成,就对FSDataIputStream调用close()方法。

在读取数据的时候,datanode一旦发生故障,DFSInputStream会尝试从这个块邻近的datanode读取数据,同时也会记住哪一个故障的datanode,并把它通知到namenode。

文件写

  1. 客户端经过调用DistributedFileSystem的create()方法新建文件。
  2. DistributedFileSystem对namenode建立RPC调用,在文件系统的命名空间新建一个文件,此时该文件尚未相应的数据块。
  3. namenode执行各类检查以确保这个文件不存在以及客户端新建文件的权限。若是各类检查都经过,就建立;不然抛出IO异常。DistributedFileSystem向客户端返回一个FSDataOutputStream对象,由此客户端开始写入数据,FSDataOutputStream会封装一个DFSoutPutstream对象,负责namenode和datanode之间的通讯。
  4. DFSOutPutstream将数据分红一个个的数据包(packet),并写入内部队列,即数据队列(data queue),DataStreamer处理数据队列,它将选择一组datanode,并据此要求namenode从新分配新的数据块。这一组datanode构成管线,假设副本数是3,因此管线有3个节点。DataStreamer将数据包流式传输到第一个datanode,该datanode存储数据包并发送给第二个datanode。。。依次类推,直到最后一个。【面试题】
  5. DFSOutPutstream维护了一个数据包队列等待datanode的收到确认回执,成为确认队列(ack queue),每个datanode收到数据包后都会返回一个确认回执,而后放到这个ack queue,等全部的datanode确认信息后,该数据包才会从队列ack queue删除。
  6. 完成数据写入后,对数据流调用close。

在写入过程当中datanode发生故障,将执行如下操做

1)关闭管线,把队列的数据报都添加到队列的最前端,以确保故障节点下游的datanode不会漏掉任何一个数据包。

2)为存储在另外一个正常的datanode的当前数据块指定一个新的标识,并把标识发送给namenode,以便在datanode恢复正常后能够删除存储的部分数据块。

3)从管线中删除故障datanode,基于正常的datanode构建一条新管线。余下的数据块写入管线中正常的datanode。namenode注意到块副本数量不足,会在另外一个节点上建立一个新的副本。后续的数据块正常接受处理。

若是多个datanode发生故障(很是少见)

只要写入了dfs.namenode.replication.min的副本数(默认1),写操做就会成功,而且这个块能够在集群中异步复制,直到达到其目的的副本数(dfs.replication的默认值3)

 

 

参考

hadoop权威指南

相关文章
相关标签/搜索