HDFS初步使用

HDFS(Hadoop Distributed File System)是可扩展、容错、高性能的分布式文件系统,异步复制,一次写入多次读取,主要负责存储。其概念和内容可以参考[1]。这里就做一个简单的实验来看一下其文件管理的功能。更多的Hadoop命令可以参考[2]

用户建立

在实验环境中,不建议使用root账号直接登录运行,所以建立一个普通账号。

# Elephant主机执行
# 安装ansible
[root@elephant ~]# yum install -y ansible
# 在/etc/ansible/hosts中新增所有主机名
# 建立ansible文件
[root@elephant ~]# mkdir playbook
[root@elephant ~]# vim ./playbook/useradd.yaml
---
- hosts: hadoop
  remote_user: root
  vars_prompt:
    - name: user_name
      prompt: Enter Username
      private: no
    - name: user_passwd
      prompt: Enter Password
      encrypt: "sha512_crypt"
      confirm: yes
  tasks:
    - name: create user
      user:
        name: "{{user_name}}"
        password: "{{user_passwd}}"

# 执行
[root@elephant ~]# ansible-playbook ./playbook/useradd.yaml
Enter Username: sujx
Enter Password:
confirm Enter Password:

PLAY [hadoop] *****************************************************************************

HDFS文件使用

我们先将准备的481M文件(access.log)上传至用户家目录,看看这个文件将在hdfs文件系统中如何存储。

[root@elephant ~]# su hdfs
[hdfs@elephant root]$ hadoop fs -mkdir /user/sujx
[hdfs@elephant root]$ hadoop fs -chown sujx /user/sujx
[hdfs@elephant root]$ su sujx -
[hdfs@elephant root]$ hdfs dfs -put access_log weblog

然后,我们通过hdfs的web控制台就可以看到文件的存储情况,可见文件以3副本的形式,按照每个128M大小的存储块分割存储在namenode之上。当前情况是分成了4块。
show
block

我们可以从lion主机中看到存储的数据块。

[root@lion ~]# tree /dfs
/dfs
`-- dn
    |-- current
    |   |-- BP-752680285-192.168.174.131-1582986010714
    |   |   |-- current
    |   |   |   |-- VERSION
    |   |   |   |-- dfsUsed
    |   |   |   |-- finalized
    |   |   |   |   `-- subdir0
    |   |   |   |       |-- subdir0
    |   |   |   |       |-- subdir1
    |   |   |   |       |-- subdir2
    |   |   |   |       |-- subdir3
    |   |   |   |       |   |-- blk_1073742734
    |   |   |   |       |   |-- blk_1073742734_1910.meta
    |   |   |   |       `-- subdir4
    |   |   |   `-- rbw
    |   |   |-- scanner.cursor
    |   |   `-- tmp
    |   `-- VERSION
    `-- in_use.lock

wHAT is HDFS?

Hadoop实现了一个分布式文件系统(Hadoop Distributed File System),简称HDFS。HDFS有高容错性的特点,并且设计用来部署在低廉的(low-cost)硬件上;而且它提供高吞吐量(high throughput)来访问应用程序的数据,适合那些有着超大数据集(large data set)的应用程序。HDFS放宽了(relax)POSIX的要求,可以以流的形式访问(streaming access)文件系统中的数据。

概念

  1. HDFS集群分为两大角色:NameNode、DataNode;
  2. NameNode负责管理整个文件系统的元数据,second namenode是namenode的冷备;
  3. DataNode 负责管理用户的文件数据块;
  4. 文件会按照固定的大小(blocksize)(128M)切成若干块后分布式存储在若干台datanode上;
  5. 每一个文件块可以有多个副本,并存放在不同的datanode上;
  6. Datanode会定期向Namenode汇报自身所保存的文件block信息,而namenode则会负责保持文件的副本数量;
  7. HDFS的内部工作机制对客户端保持透明,客户端请求访问HDFS都是通过向namenode申请来进行;

写过程

HDFS_write

  1. Client调用DistributedFileSystem对象的create方法,创建一个文件输出流(FSDataOutputStream)对象
  2. 通过DistributedFileSystem对象与Hadoop集群的NameNode进行一次RPC远程调用,在HDFS的Namespace中创建一个文件条目(Entry),该条目没有任何的Block
  3. 通过FSDataOutputStream对象,向DataNode写入数据,数据首先被写入FSDataOutputStream对象内部的Buffer中,然后数据被分割成一个个Packet数据包
  4. 以Packet最小单位,基于Socket连接发送到按特定算法选择的HDFS集群中一组DataNode(正常是3个,可能大于等于1)中的一个节点上,在这组DataNode组成的Pipeline上依次传输Packet
  5. 这组DataNode组成的Pipeline反方向上,发送ack,最终由Pipeline中第一个DataNode节点将Pipeline ack发送给Client
  6. 完成向文件写入数据,Client在文件输出流(FSDataOutputStream)对象上调用close方法,关闭流
  7. 调用DistributedFileSystem对象的complete方法,通知NameNode文件写入成功

读过程

HDFS_read

  1. Client向NameNode发起RPC请求,来确定请求文件block所在的位置
  2. NameNode会视情况返回文件的部分或者全部block列表,对于每个block,NameNode都会返回含有该block副本的DataNode地址
  3. 这些返回的DN地址,会按照集群拓扑结构得出DataNode与客户端的距离,然后进行排序,排序两个规则:网络拓扑结构中距离Client的排在前;心跳机制中超时汇报的DN状态为STALE,这样的排在后
  4. Clietn选取排序靠前的DataNode来读取block,如果客户端本身就是DataNode,那么将从本地直接获取数据
  5. 底层本质是建立Socket Stream(FSDataInputStream) ,重复调用父类DataInputStream的read方法,知道这个块上的数据读取完毕
  6. 当读完列表的block后,若文件读取还没有结束,客户端会继续想NameNode获取下一批的block列表
  7. 读取完一个Block都会进行checksum验证,如果读取DataNode时出现错误,客户端会通知NameNode,然后再从下一个拥有该block副本的DataNode继续读取。注: 如果在读取过程中DFSInputStream检测到block错误,DFSInputStream也会检查从datanode读取来的数据的校验和,如果发现有数据损坏,它会把坏掉的block报告给namenode同时重新读取其他datanode上的其他block备份
  8. read方法是并行的读取block信息,不是一块一块的读取,NameNode只是返回Client请求包含块的DataNode地址,并不是返回请求块的数据
  9. 最终读取哎所有的block会合并成一个完整的最终文件

副本放置策略

  1. 第一个副本:放置在上传文件的DN;如果是集群外提交,则随机挑选一台磁盘不太满,CPU不太忙的节点
  2. 第二个副本:放置在于第一个副本不同的机架的节点上
  3. 第三个副本:与第二个副本相同机架的节点
  4. 更多副本:随机节点

NameNode 内存使用

NameNode内存数据主要对整个文件系统元数据的管理。Namenode目前元数据管理可以分成两个层次,一个是Namespace的管理层,这一层负责管理HDFS分布式文件系统中的树状目录和文件结构;另一层则为Block管理层,这一层负责管理HDFS分布式文件系统中存储文件到物理块之间的映射关系BlocksMap元数据。其中对Namespace的管理数据除在内存常驻外,会定期Flush到持久化设备中;对BlocksMap元数据的管理只存在内存;当NameNode发生重启,需要从持久化设备中读取Namespace管理数据,并重新构造BlocksMap。

除了对文件系统本身元数据的管理外,NameNode还需要维护DataNode本身的元数据,这部分空间相对固定,且占用空间较小。

从实际Hadoop集群环境历史数据看,当Namespace中包含INode(目录和文件总量)~140M,数据块数量~160M,常驻内存使用量达在~50G。随着数据规模的持续增长,内存占用接近同步线性增长。在整个HDFS服务中,NameNode的核心作用及内存数据结构的重要地位,所以分析内存使用情况对维护HDFS服务稳定性至关重要。

漫画HDFS

HDFS_001
HDFS_002
HDFS_003