HDFS源码解析(二)

上一篇讲到了namenode的格式化,格式化方法中有

FSImage fsImage = new FSImage(conf, nameDirsToFormat, editDirsToFormat);
    try {
      FSNamesystem fsn = new FSNamesystem(conf, fsImage);

今天主要讲讲FSImage ,FSNamesystem 分别在(1),(2)中

(1)先来看FSImageFSImage处理checkpointing(检查点),并记录到文件命名空间编辑日志中。

fsimage在磁盘上对应上一篇文章提到的/home/hadoop/dfs/name路径。目录下有currentimagein_use.lock;在current目录下有edits日志,fsimage内存镜像,fstime镜像时间,VERSION版本信息。

FSImage常用操作有loadFSImage(加载文件系统镜像),saveFSImage(保存文件系统镜像)

在loadFSImage中,最终会调用FSImageFormat类中的load(File curFile)方法,代码如下:

public void load(File curFile) throws IOException {
      checkNotLoaded(); // 保证是第一次加载时执行下面的语句
      assert curFile != null : "curFile is null"; // 断言

      StartupProgress prog = NameNode.getStartupProgress(); // 获取启动进度
      Step step = new Step(StepType.INODES);
      prog.beginStep(Phase.LOADING_FSIMAGE, step);
      long startTime = now(); // 开始

      //
      // Load in bits
      //
      MessageDigest digester = MD5Hash.getDigester();
      DigestInputStream fin = new DigestInputStream(
           new FileInputStream(curFile), digester); // 获取输入流

      DataInputStream in = new DataInputStream(fin); // 包装输入流
      try {
        // read image version: first appeared in version -1
        int imgVersion = in.readInt(); // 读取镜像版本号
        if (getLayoutVersion() != imgVersion) { // 判断版本是否一致,不一致抛异常
          throw new InconsistentFSStateException(curFile, 
              "imgVersion " + imgVersion +
              " expected to be " + getLayoutVersion());
        }
        boolean supportSnapshot = NameNodeLayoutVersion.supports( // 判断是否支持快照
            LayoutVersion.Feature.SNAPSHOT, imgVersion);
        if (NameNodeLayoutVersion.supports(
            LayoutVersion.Feature.ADD_LAYOUT_FLAGS, imgVersion)) {
          LayoutFlags.read(in);
        }

        // read namespaceID: first appeared in version -2
        in.readInt(); // 读取命名空间编号

        long numFiles = in.readLong(); // 文件数量
<span style="white-space:pre">	</span>......
在saveFSImage中,最终调用FSImageFormatProtobuf中save(File file, FSImageCompression compression)方法,代码如下

void save(File file, FSImageCompression compression) throws IOException {
      FileOutputStream fout = new FileOutputStream(file); // 创建输出流
      fileChannel = fout.getChannel(); // 获取网络套接字的通道,用过java nio的朋友应该清楚
      try {
        saveInternal(fout, compression, file.getAbsolutePath().toString()); // 在该方法中,underlyingOutputStream.write(FSImageUtil.MAGIC_HEADER)进行持久化操作
      } finally {
        fout.close();
      }
    }
(2)对于hadoop集群,master节点存储3种类型元数据:文件和数据块的命名空间,文件和数据块的对应关系,每个数据块副本的存放地点。所有的元数据都保存在内存中,前两种类型也会以记录变更日志的方式记录在系统日志文件中。

文件系统的存储和管理都交给了FSNameSystem类,我们就看看他的注释:

/***************************************************
 * FSNamesystem does the actual bookkeeping work for the // 此类为datanode做实际的簿记工作
 * DataNode.
 *
 * It tracks several important tables.
 *
 * 1)  valid fsname --> blocklist  (kept on disk, logged) // 文件系统命名空间到数据块列表的映射,保存在磁盘上并记录日志
 * 2)  Set of all valid blocks (inverted #1) // 合法数据块集合,上面的逆关系
 * 3)  block --> machinelist (kept in memory, rebuilt dynamically from reports) // 数据块到datanode的映射,保存在内存中,由datanode上报动态重建
 * 4)  machine --> blocklist (inverted #2) // datanode上保存的数据块列表,上面的逆关系
 * 5)  LRU cache of updated-heartbeat machines 近期最少使用缓存队列,保存datanode的心跳信息
 ***************************************************/


FSNamesystem 有一个FSDirectory成员变量,它保存文件名到数据块列表的映射,类中有添加文命名空间,添加文件,添加数据块,创建目录等操作。

下面是数据块相关的方法

  @Override // FSNamesystemMBean
  @Metric
  public long getPendingReplicationBlocks() { // 返回正在复制的数据块
    return blockManager.getPendingReplicationBlocksCount();
  }

  @Override // FSNamesystemMBean
  @Metric
  public long getUnderReplicatedBlocks() { // 返回需要复制的数据块
    return blockManager.getUnderReplicatedBlocksCount();
  }

  /** Returns number of blocks with corrupt replicas */
  @Metric({"CorruptBlocks", "Number of blocks with corrupt replicas"})
  public long getCorruptReplicaBlocks() { // 返回损坏的数据块
    return blockManager.getCorruptReplicaBlocksCount();
  }

  @Override // FSNamesystemMBean
  @Metric
  public long getScheduledReplicationBlocks() { // 返回当前正在处理的数据块复制数目
    return blockManager.getScheduledReplicationBlocksCount();
  }

  @Override
  @Metric
  public long getPendingDeletionBlocks() { // 返回正在删除的数据块数目
    return blockManager.getPendingDeletionBlocksCount();
  }

  @Metric
  public long getExcessBlocks() { // 返回超过配额的数据块数目
    return blockManager.getExcessBlocksCount();
  }
  
  // HA-only metric
  @Metric
  public long getPostponedMisreplicatedBlocks() { // 返回延期或错过复制的数据块数目,仅在ha的情况下
    return blockManager.getPostponedMisreplicatedBlocksCount();
  }


第1章 HDFS 1 1.1 HDFS概述 1 1.1.1 HDFS体系结构 1 1.1.2 HDFS基本概念 2 1.2 HDFS通信协议 4 1.2.1 Hadoop RPC接口 4 1.2.2 流式接口 20 1.3 HDFS主要流程 22 1.3.1 HDFS客户端读流程 22 1.3.2 HDFS客户端写流程 24 1.3.3 HDFS客户端追加写流程 25 1.3.4 Datanode启动、心跳以及执行名字节点指令流程 26 1.3.5 HA切换流程 27 第2章 Hadoop RPC 29 2.1 概述 29 2.1.1 RPC框架概述 29 2.1.2 Hadoop RPC框架概述 30 2.2 Hadoop RPC的使用 36 2.2.1 Hadoop RPC使用概述 36 2.2.2 定义RPC协议 40 2.2.3 客户端获取Proxy对象 45 2.2.4 服务器获取Server对象 54 2.3 Hadoop RPC实现 63 2.3.1 RPC类实现 63 2.3.2 Client类实现 64 2.3.3 Server类实现 76 第3章 Namenode(名字节点) 88 3.1 文件系统树 88 3.1.1 INode相关类 89 3.1.2 Feature相关类 102 3.1.3 FSEditLog类 117 3.1.4 FSImage类 138 3.1.5 FSDirectory类 158 3.2 数据块管理 162 3.2.1 Block、Replica、BlocksMap 162 3.2.2 数据块副本状态 167 3.2.3 BlockManager类(done) 177 3.3 数据节点管理 211 3.3.1 DatanodeDescriptor 212 3.3.2 DatanodeStorageInfo 214 3.3.3 DatanodeManager 217 3.4 租约管理 233 3.4.1 LeaseManager.Lease 233 3.4.2 LeaseManager 234 3.5 缓存管理 246 3.5.1 缓存概念 247 3.5.2 缓存管理命令 247 3.5.3 HDFS集中式缓存架构 247 3.5.4 CacheManager类实现 248 3.5.5 CacheReplicationMonitor 250 3.6 ClientProtocol实现 251 3.6.1 创建文件 251 3.6.2 追加写文件 254 3.6.3 创建新的数据块 257 3.6.4 放弃数据块 265 3.6.5 关闭文件 266 3.7 Namenode的启动和停止 268 3.7.1 安全模式 268 3.7.2 HDFS High Availability 276 3.7.3 名字节点的启动 301 3.7.4 名字节点的停止 306 第4章 Datanode(数据节点) 307 4.1 Datanode逻辑结构 307 4.1.1 HDFS 1.X架构 307 4.1.2 HDFS Federation 308 4.1.3 Datanode逻辑结构 310 4.2 Datanode存储 312 4.2.1 Datanode升级机制 312 4.2.2 Datanode磁盘存储结构 315 4.2.3 DataStorage实现 317 4.3 文件系统数据集 334 4.3.1 Datanode上数据块副本的状态 335 4.3.2 BlockPoolSlice实现 335 4.3.3 FsVolumeImpl实现 342 4.3.4 FsVolumeList实现 345 4.3.5 FsDatasetImpl实现 348 4.4 BlockPoolManager 375 4.4.1 BPServiceActor实现 376 4.4.2 BPOfferService实现 389 4.4.3 BlockPoolManager实现 396 4.5 流式接口 398 4.5.1 DataTransferProtocol定义 398 4.5.2 Sender和Receiver 399 4.5.3 DataXceiverServer 403 4.5.4 DataXceiver 406 4.5.5 读数据 408 4.5.6 写数据(done) 423 4.5.7 数据块替换、数据块拷贝和读数据块校验 437 4.5.8 短路读操作 437 4.6 数据块扫描器 437 4.6.1 DataBlockScanner实现 438 4.6.2 BlockPoolSliceScanner实现 439 4.7 DirectoryScanner 442 4.8 DataNode类的实现 443 4.8.1 DataNode的启动 444 4.8.2 DataNode的关闭 446 第5章 HDFS客户端 447 5.1 DFSClient实现 447 5.1.1 构造方法 448 5.1.2 关闭方法 449 5.1.3 文件系统管理与配置方法 450 5.1.4 HDFS文件与操作方法 451 5.1.5 HDFS文件读写方法 452 5.2 文件读操作与输入流 452 5.2.1 打开文件 452 5.2.2 读操作――DFSInputStream实现 461 5.3 文件短路读操作 481 5.3.1 短路读共享内存 482 5.3.2 DataTransferProtocol 484 5.3.3 DFSClient短路读操作流程 488 5.3.4 Datanode短路读操作流程 509 5.4 文件写操作与输出流 512 5.4.1 创建文件 512 5.4.2 写操作――DFSOutputStream实现 516 5.4.3 追加写操作 543 5.4.4 租约相关 546 5.4.5 关闭输出流 548 5.5 HDFS常用工具 549 5.5.1 FsShell实现 550 5.5.2 DFSAdmin实现 552
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值