Hadoop HDFS详解和常用指令

HDFS:

  1. 是Hadoop中用于数据的分布式存储的组件
  2. 根据Google论文《The Google File System》来设计的

常用指令

指令 说明
hadoop fs -put 向HDFS上传文件
hadoop fs -mkdir 在HDFS上创建了目录(实际上只是一个路径标记)
hadoop fs -get 下载
hadoop fs -rm 删除文件
hadoop fs -rmdir 删除目录
hadoop fs -rmr 递归删除
hadoop fs -ls 查看指定路径下的子文件和子目录
hadoop fs -lsr 递归查看
hadoop fs -cat 查看指定文件中的内容
hadoop fs -tail 查看指定文件的最后1000个字节的内容
hadoop fs -mv 剪切文件
hadoop fs -cp 复制文件
hadoop fs -touchz 创建一个空文件
hadoop fsck /test/txt/a.txt -files -blocks -locations -racks

一、基本结构

  1. 在HDFS中,对于文件是进行切块保存
  2. HDFS中有2类主要的节点:NameNode和DataNode
  3. NameNode负责管理DataNode
  4. DataNode负责存储数据
  5. HDFS会对文件块进行自动的备份,每一个备份称之为复本(Replication),HDFS默认是3个复本
  6. 如果某一个DataNode宕机,那么在HDFS中默认将这个DataNode所存储的复本再进行一次备份,保证指定的复本数量

二、Block

  1. 在HDFS中,会对文件进行切块,每一个块实际上就是一个Block
  2. Block是HDFS中存储的基本单位
  3. Block在Hadoop1.0中的大小是64M,在Hadoop2.0中的大小是128M
  4. 如果一个文件或者数据的大小不满足Block的大小,那么这个文件或者数据是多大那么对应的Block就是多大
  5. 切块的意义:
    a. 便于存储超大文件
    b. 便于进行快速的备份
  6. HDFS对每一个Block分配一个递增的编号

三、NameNode

  1. NameNode是HDFS中的核心节点,用于管理其他的DataNode
  2. NameNode本身会记录元数据(Meta Data)
  3. 元数据包含:
    a. 文件的存储路径,例如/a.log,/test/b.txt
    b. 复本数量
    c. 文件所对应的文件块 — Block
    d. 每一个Block的存储节点
  4. 每一条元数据一般是在150B大小左右
  5. 只有写请求会产生元数据,读请求不产生元数据
  6. 元数据在NameNode中存储在内存以及磁盘中
  7. 元数据存储在内存中的目的是为了快速查询
  8. 元数据存储在磁盘中是为了崩溃恢复
  9. 元数据存储在磁盘上的位置由core-site.xml中的属性hadoop.tmp.dir来决定,在指定的目录的子目录dfs/name/current下
  10. 元数据存储的文件:
    a. edits:记录NameNode接收的每一次的写(上传、删除、追加)请求
    b. fsimage:记录元数据,但是这个文件中的元数据不是实时的
  11. 当NameNode接收到一个新的写请求的时候,会先将这个请求写到edits文件中,当edits文件写成功之后,再去更改内存中的元数据,当内存中的元数据更改完毕之后,会个客户端返回一个成功信号
  12. edits和fsimage在触发合并条件的时候会进行合并:
    a. 时间:由(core-site.xml)fs.checkpoint.period属性决定,默认数量是3600,默认时间单位是秒
    b. 空间:由(core-site.xml)fs.checkpoint.size属性决定,默认是64M,表示当edits文件到达64M的时候会将其中的操作更新到fsimage中
    c. 重启:NameNode重新启动的时候,自动触发edits和fsiamge的合并
    d. 强制:指令 hadoop dfsadmin -rollEdits
  13. 内存中元数据 = edits中的操作+fsimage中的元数据
  14. 在Hadoop1.0中,NameNode有且只有一个,也就意味着NameNode存在单点故障
  15. 在Hadoop2.0的伪分布式中,NameNode也只有一个;但是在Hadoop2.0的完全分布式中,可以通过舍弃SecondaryNameNode的方式来搭建2个NameNode避免NameNode的单点故障
  16. 在完全分布式中,如果存在NameNode和SecondaryNameNode,那么合并过程是发生在SecondaryNameNode上;如果舍弃了SecondaryNameNode,合并过程只能发生在NameNode上
  17. DataNode通过心跳机制(每隔固定时间)来给NameNode发送心跳信号
  18. 心跳信号包含:
    a. 当前节点的状态
    b. 当前DataNode存储的数据
  19. 在HDFS启动/重启的时候,自动的触发edits和fsimage的合并,合并完成之后,会将fsimage中的元数据加载到内存中,然后会进行一系列的校验(等待DataNode的心跳,校验数据的完整性),在这个过程中,HDFS不对外提供写服务只提供读服务,这种情况称之为安全模式
  20. HDFS当完成所有的校验之后会自动退出安全模式
  21. 如果在伪分布式下,设置的复本数量>1,那么就会无法退出安全模式

四、DataNode

  1. DataNode用于存储数据,数据是以Block形式存储
  2. DataNode通过心跳机制(RPC)来向NameNode发送心跳信号
  3. DataNode每隔3s向NameNode发送一次心跳
  4. 如果NameNode超过10min没有收到DataNode的心跳,那么NameNode认为这个DataNode已经lost(丢失)
  5. 当NameNode认为DataNode已经lost的时候,NameNode要将这个DataNode上的Block备份到其他的节点上

五、SecondaryNameNode

  1. SecondaryNameNode不是NameNode热备,只是辅助NameNode进行元数据的合并,SecondaryNameNode也能起到一定的备份作用
  2. 合并过程
    Hadoop HDFS详解和常用指令
  3. SecondaryNameNode设计的目的是为了提高HDFS的运行效率,但是实际开发过程中往往会舍弃SecondaryNameNode,而是采用双NameNode机制来实现NameNode的热备

六、多复本放置策略

  1. 第一个复本:如果是从集群内部上传,哪个节点上传第一个复本就放在哪个节点上;如果是从集群外部上传,那么NameNode会选择一个相对比较空闲的DataNode存储第一个复本
  2. 第二个复本:放在和第一个复本不同机架的节点上
  3. 第三个复本:放在和第二个复本相同机架的节点上
  4. 更多复本:选择相对空闲的节点来放置

七、机架感知策略

  1. 机架感知策略本质上是建立节点和机架的映射关系
  2. 机架指的不是物理机架而是逻辑机架
  3. 可以将不同物理机架上的节点映射到同一个逻辑机架上
  4. 一般是将同一个物理机架上的节点放到同一个逻辑机架上

dfs目录

  1. 用于存储HDFS中的数据的目录
  2. dfs目录在格式化的时候产生
  3. dfs下包含:data/name/namesecondary在完全分布式下应该是在不同的节点中
  4. 当HDFS第一次启动的时候,edits和fsimage在启动一分钟之后自动合并一次;后续就是按照指定时间间隔进行合并
  5. HDFS会对每一次的操作分配一个事务id – txid
    a. edits_X-Y:X表示edits文件开始记录的事务id,Y表示结束记录的事务id
    b. fsimage_X:对应的是edits中的起始id
  6. 查看edits文件:hdfs oev -i edits_XXX -o XXX.xml
  7. 上传文件:
    a. OP_ADD:先在HDFS上创建一个同名文件.COPYING
    b. OP_ALLOCATE_BLOCK_ID:表示分配Blockid
    c. OP_SET_GENSTAMP_V2:表示分配给当前时间戳一个编号
    d. OP_ADD_BLOCK:利用流将数据写入到对应的Block上
    e. OP_CLOSE:关闭文件
    f. OP_RENAME_OLD:重命名
  8. 文件关闭之后不允许再次写入
  9. 查看fsimage文件:hdfs oiv -i fsimage_XXX -o XXXX.xml -p XML
  10. edits_X-Y表示已经合并过的文件;新的操作是写到edits_inprogress_X中
  11. fsimage_X.md5用于进行对fsimage_X的校验
  12. seen_txid记录最新的事务id
  13. NameNode每格式化一次,都会自动计算出一个clusterID,记录在VERSION文件中。NameNode会把自己的clusterID分发给每一个它管理的DataNode上,利用这个clusterID作为标记,确定NameNode所要管理的这些DataNode
  14. in_use.lock表示当前节点的NameNode/DataNode已经启动,不需要再二次启动

执行流程

一、读取流程

  1. 客户端发起RPC请求到NameNode
  2. NameNode收到请求之后,查询元数据,获取到文件所对应的切块地址;将地址放入一个队列中,然后将全部或者部分地址返回给客户端
  3. 客户端收到队列之后,从队列中将第一个Block的地址取出
  4. 客户端从地址中选取一个较近的节点来读取数据
  5. 读取完Block之后,会对读取完的数据进行一次checkSum的校验:如果校验成功,那么接着获取下一个Block的地址,选取节点进行读取;如果校验失败,客户端先发送信号给NameNode,得从当前Block所存储的其他节点中重新读取
  6. 读完这一批的Block之后,客户端会给NameNode发送信号获取下一批的Block的地址
  7. 当客户端读取完所有的Block之后,客户端会NameNode发送信号,NameNode会将文件关闭(关流)

二、写入流程

  1. 客户端发起RPC请求到NameNode
  2. NameNode收到请求之后,会请求进行校验:
    a. 校验这个发起这个请求的用户是否有权限操作
    b. 校验要上传的路径中是否有同名的文件
  3. 如果校验成功,则将该操作更新到edits中并且更新内存中的元数据 - 计算文件的大小,计算切块的数量,给每一个Block分配存储的节点
  4. NameNode将存储节点放入一个队列中返回给客户端
  5. 客户端在收到队列之后,从中取出第一个节点位置,然后将第一个文件块封装成Packets对象写到对应的节点上
  6. 当客户端写完第一个复本之后,当前DataNode会自动通过pipeline(管道,底层是基于Channel)将这个复本备份到其他的DataNode上
  7. 当将3个复本都写完之后,会客户端发送ack信号表示写入成功
  8. 客户端收到ack之后,就会继续写第二个Block
  9. 客户端在写完全部的Block之后,通知NameNode将文件关闭。文件关闭之后就不能改动

三、删除流程

  1. 客户端发起RPC请求到NameNode
  2. NameNode接收到请求之后,将操作记录到edits文件中,然后更新内存
  3. NameNode就会返回一个成功信号给客户端,表示文件删除成功;注意,此时文件并没有从HDFS上真正移除
  4. NameNode等待DataNode的下一次心跳,NameNode会对DataNode所发送的心跳信息进项校验
  5. NameNode发现DataNode中依然存储着之前的数据,NameNode就会给DataNode发送信号要求删除对应的数据
  6. DataNode收到NameNode的信号之后,才会真正删除这个文件所对应的数据块

特点

  1. 优点:
    a. 支持存储超大文件 - 切块
    b. 快速应对和检测节点故障 - 心跳机制
    c. 流式数据访问,提高吞吐量
    d. 高容错性 - 多复本
    e. 便于进行横向扩展,并且横向扩展的成本较低
  2. 缺点:
    a. 不建议存储大量的小文件
    b. 不支持低延迟访问
  3. 简化的一致性模型:支持一次写入多次读取,但是不支持修改。从Hadoop2.0开始,支持追加写入,但是写完的数据依然不能更改
  4. 不支持事务