HDFS 笔记

195 阅读3分钟

HDFS

HDFS 块大小--128MB,与面向单一磁盘的文件系统不同,HDFS 中小于一个块大小的文件不会占据整个块的空间。

HDFS 块为 128MB,最小化寻址开销,trade off 磁盘传输数据的时间和定位块开始位置的时间。

HDFS 存储大量小文件弊端:

  1. MapReduce 处理数据最佳速度刚好与数据在集群中传输速度相同,而小文件将增加运行作业寻址次数;
  2. 浪费 namenode 的内存。

处理方式:

  1. 使用 sequence file 合并小文件:将文件名作为 key,文件内容作为 value;
  2. 使用 CombineFileInputFormat。

HDFS 读文件

HDFS read

客户端直接连接到 datanode 检索数据

HDFS 写文件

HDFS write

NameNode 目录结构

在格式化时创建:

 ${dfs.namenode.name.dir}/
 ├── current
 │   ├── VERSION
 │   ├── edits_0000000000000000001-0000000000000000019
 │   ├── edits_inprogress_0000000000000000020
 │   ├── fsimage_0000000000000000000
 │   ├── fsimage_0000000000000000000.md5
 │   ├── fsimage_0000000000000000019
 │   ├── fsimage_0000000000000000019.md5
 │   └── seen_txid
 └── in_use.lock

edit log 在概念上是一个 entity,但是在磁盘上是多个文件,每个文件称为 segment,同一时间只有一个文件处于打开状态(edits_inprogress_*),先更新日志,然后向 client 返回事务执行成功。

fsimage 文件包含文件系统中所有目录和文件 inode 的序列化信息。每个 inode 是一个文件或目录的元数据的内部描述方式。
fsimage 不记录 DataNode 的 block 存储信息,NameNode 将块信息映射到内存中。DataNode 加入集群后,NameNode 通过向 DataNode 询问 block lists 建立映射关系。

安全模式
NameNode 启动时,首先进入安全模式(首次启动除外),只有访问文件系统元数据的操作能成功执行,文件修改操作(写、删除或重命名)均会失败。如果满足「最小副本条件」,则在 30s 之后退出安全模式。

% hdfs dfsadmin -safemode get
    Safe mode is ON
% hdfs dfsadmin -safemode wait
    # command to read or write a file
% hdfs dfsadmin -safemode enter
    Safe mode is ON
% hdfs dfsadmin -safemode leave
    Safe mode is OFF

Secondary namenode

创建 CheckPoint 步骤:

  1. 请求 NameNode 停止使用 edits 文件,同时 NameNode 更新 seen_txid 文件;
  2. Secondary namenode 从 NameNode 获取最新的 fsimage 和 edits 文件(HTTP GET);
  3. Secondary namenode 将 fsimage 载入内存,逐一执行 edits 事务,创建新的 fsimage;
  4. 将新的 fsimage 发送回 NameNode(HTTP PUT),NameNode 将其保存为临时的 .ckpt 文件;
  5. NameNode 重新命名临时的 fsimage 以便日后使用。

The checkpointing process

为何 Secondary namenode 和 NameNode 需要相近内存需求?因为 Secondary namenode 也把 fsimage 文件载入内存。

DataNode 目录结构

 ${dfs.datanode.data.dir}/
 ├── current
 │   ├── BP-526805057-127.0.0.1-1411980876842
 │   │   └── current
 │   │       ├── VERSION
 │   │       ├── finalized
 │   │       │   ├── blk_1073741825
 │   │       │   ├── blk_1073741825_1001.meta
 │   │       │   ├── blk_1073741826
 │   │       │   └── blk_1073741826_1002.meta
 │   │       └── rbw
 │   └── VERSION
 └── in_use.lock

HDFS Federation

在联邦环境下,每一个 namenode 维护一个命名空间卷(namespace volume),由命名空间元数据和一个数据块池(block pool)组成,每个 namenode 管理文件系统命名空间一部分。

HDFS 高可用性(HA)

Hadoop 2 增加支持,配置一对 active-standby namenode。

  1. 编辑日志共享;
  2. datanode 同时向两个 namenode 发送数据块处理报告;
  3. client 使用特殊机制处理 namenode 失效问题;
  4. Secondary namenode 被 standby namenode 包含。
  • 两种共享存储:NFS 过滤器和群体日志管理器(QJM,quorum journal manager)。

  • 故障转移控制器(failover controller),默认使用 ZooKeeper 来确保有且仅有一个 activity namenode,每个 namenode 都运行该控制器,namenode 失效时切换 namenode。

管理员主动发起故障转移,称为 graceful failover。确保先前 namenode 不会影响系统,称为规避(fencing)。
对 QJM 设置 ssh 规避命令杀死 namenode。使用 NFS 过滤器实现共享编辑日志需要更有力规避方法。


Hadoop 文件系统

Hadoop 文件系统 URI 方案 Java 实现
Local file fs.LocalFileSystem
hdfs hdfs hdfs.DistributedFileSystem
WebHDFS webhdfs -
Secure WebHDFS swebhdfs -
HAR har fs.HarFileSystem
View viewfs viewfs.ViewFileSystem
FTP ftp -
Hadoop FS scheme URI 格式
WebHDFS webhdfs://<HOST>:<HTTP_PORT>/<PATH>
Secure WebHDFS swebhdfs://<HOST>:<HTTP_PORT>/<PATH>
HDFS hdfs://<HOST>:<RPC_PORT>/<PATH>
REST API http://<HOST>:<HTTP_PORT>/webhdfs/v1/<PATH>?op=...

详见 WebHDFS REST API

通过 FileSystem API 读取数据

  1. 获取 FS 实例:
public static FileSystem get ( Configuration conf ) throws IOException
public static FileSystem get ( URI uri, Configuration conf ) throws IOException
public static FileSystem get ( URI uri, Configuration conf, String user ) throws IOException

获取本地 FS:

public static LocalFileSystem getLocal ( Configuration conf ) throws IOException
  1. 调用 open() 函数获取文件输入流:
public FSDataInputStream open ( Path file ) throws IOException
public abstract FSDataInputStream open ( Path file, int buffersize ) throws IOException

FSDataOutputStream 只能在文件末尾写入,刷新方法包含:

  1. flush():当前正写入的块是不可见的;
  2. hflush():不能保证写到磁盘中,但写入内存,且可见;
  3. hsync():写入磁盘

其他方法

  1. 创建目录:
public boolean mkdirs ( Path file ) throws IOException
  1. FileStatus 类封装了文件系统中文件和目录的元数据,FileSystem 类中 getFileStatus() 方法获取 FileStatus 对象;
  2. 列出文件:FileSystem 中的 listStatus()
  3. 文件模式,执行通配(globbing):
public FileStatus[] globStatus ( Path pathPattern ) throws IOException
public FileStatus[] globStatus ( Path pathPattern, PathFilter pathFilter ) throws IOException