hdfs读写原理

3个概念

block
这个块就是block,它是最大的一个单位。一般为128MB,当然你可以去改,不顾不推荐。因为块太小:寻址时间占比过高。块太大:Map任务数太少,作业执行速度变慢。

packet
packet是第二大的单位,它是client端向DataNode,或DataNode的PipLine之间传数据的基本单位,默认64KB。

chunk
chunk是最小的单位,它是client向DataNode,或DataNode的PipLine之间进行数据校验的基本单位,默认512Byte,因为用作校验,故每个chunk需要带有4Byte的校验位。所以实际每个chunk写入packet的大小为516Byte。由此可见真实数据与校验值数据的比值约为128
: 1。(即64*1024 / 512)

写数据是输出流

  1. 客户端向namenode发送上传文件的请求
  2. namenode会检查目标文件,目录,权限
  3. 通过检查,客户端对文件进行切分,比如一个文件180M,会分为两个block块,DFSOutputStream会把数据切成一个个小的packet,然后排成队 列data queue
  4. 切分完后客户端再次向namenode发送请求, namenode检查datenode的信息,然后返回可用的datenode信息
  5. 客户端会选择就近的一台datenode上传数据,client每向第一个DataNode写入一个packet,这个packet便会直接在pipeline里传给第二个、第三个…DataNode。
  6. packet 到达DataNode3后做校验,将校验结果逆着pipeline回传给ClientNode。DataNode3将校验结果传给DataNode2,DataNode2做校验后将校验结果传给DataNode1,DataNode1做校验后将校验结果传给ClientNode。ClientNode根据校验结果判断,如果”成功“,则将ackqueue确认队列中的packet 删除;如果”失败“,则将ackqueue确认队列中的package取出,重新放入到dataqueue数据队列末尾,等待重新沿pipeline发送。
  7. 每个DataNode写完一个block后,通知namenode把block元数据同步到内存中
  8. 客户端关闭pipeline
  9. 全部block写完,关闭输出流
    hdfs读写原理

读数据输入流

  1. 客户端通过FileSystem的open()获取输入流InputStream
  2. 客户端通过rpc发送读取数据请求
  3. .namenode查询元数据,找到文件块所在的datenode的地址并返回
  4. 客户端调用read 方法读取数据,选择就近的一台datenode,建立socket流
  5. datenode开始发送数据
  6. 客户端以packet为单位接收,先缓存在本地,然后写入目标文件
  7. 到达数据块末端,关闭与这个DataNode 的连接,然后重新查找下一个数据块
  8. 其他的块不断的加到前面的块中,最后合并成查询文件
  9. 关闭输入流
    hdfs读写原理

如何保证数据完整性

Hadoop在写入数据到HDFS上时,会为每一个固定长度pachet(默认是512字节)的数据执行一次“校验和chunk”,“校验和”的值和数据一起保存起来。
DataNode在存储客户端上传的数据之前计算一个校验和,客户端从DataNode读取数据时也会计算一个校验和,两个校验和如果不相同就说明数据存在错误

DataNode运行着一个后台进程(DataBlockScanner),定期对存储在其上面的block进行检测“检验和”,然后将检测结果向NameNode报告

NameNode校验和不对的block标记为“已损坏”,namenode就不会为客户端指向这个block,也不会用这个block去复制到其他datanode
NameNode会把一个好的block复制到另一个datanode上
NameNode删除掉坏的block。