HDFS内存存储

前言


上一篇文章主要阐述了HDFS Cache缓存方面的知识,本文继续带领大家了解HDFS内存存储相关的内容.在HDFS中,CacheAdmin设置的目标文件缓存是会存放于DataNode的内存中,但是另外一种情况也可以将数据存放在DataNode的内存里.就是之前HDFS异构存储中提到的内存存储策略,LAZY_PERSIST.换句话说,本文也是对HDFS内存存储策略的一个更细致的分析.考虑到LAZY_PERSIST内存存储与其他存储策略类型的不同之处,做这样的一个分析还是比较有意义的.

HDFS内存存储原理


对于内存存储,可能很多人会存有这么几种看法,

  • 第一种,数据就是临时维持在内存中的,服务一停止,数据全没.
  • 第二种,数据还是存在与内存种,但是服务停止的时候,做持久化处理,最终全部写入到磁盘.

仔细来看以上这2种观点,其实都有不小的瑕疵.
首先第一个观点,服务一旦停止,内存数据全丢,这个是无法接受的,我们可以忍受内存中少量的数据丢失,但是全丢就不是特别好的处理方式了.而且这个也有点不合理,内存的存储空间是有限的,如果不及时存储一部分数据,内存空间迟早会耗尽.

然后是第二个观点,第二个方案种是在服务停止退出的时候做持久化操作,但是他同样会面临上面提到的内存空间的限制问题.而且假设机器的内存是足够大的,那么最后写入磁盘的那个阶段想必也不会那么快,因为数据可能会很多.

所以一般的通用的比较好的做法是异步的做持久化,什么意思呢

内存存储新数据的同时,持久化距离当前时刻最远(存储时间最早)的数据

换一个通俗的解释,好比我有个内存数据块队列,在队列头部不断有新增的数据块插入,就是待存储的块,因为资源有限 ,我要把队列尾部的块,也就是早些时间点的块持久化到磁盘中,然后才有空间腾出来存新的块.然后形成这样的一个循环,新的块加入,老的块移除,保证了整体数据的更新.

HDFS的LAZY_PERSIST内存存储策略用的就是这套方法.下面是一张原理图:

这里写图片描述

上文描述的原理在图中的表示其实是4,6,的步骤.写数据的RAM,然后异步的写到Disk.前面几个步骤是如何设置StorageType的操作,这个在下文种会具体提到.所以上图所示的大体步骤可以归纳为如下:

  • 第一步,对目标文件目录设置StoragePolicy为LAZY_PERSIST的内存存储策略.
  • 第二步,客户端进程向NameNode发起创建/写文件的请求.
  • 第三步,然后请求到具体的DataNode,DataNode会把这些数据块写入RAM内存中,同时启动异步线程服务将内存数据持久化到磁盘上.

内存的异步持久化存储,就是明显不同于其他介质存储数据的地方.这应该也是LAZY_PERSIST的名称的源由吧,数据不是马上落盘,而是”lazy persisit”懒惰的方式,延时的处理.

Linux 虚拟内存盘


这里需要了解一个额外的知识点,Linux 虚拟内存盘.之前我也是一直有个疑惑,内存也可以当作一个块盘使用?内存不就是临时存数据用的吗?于是在学习此模块知识之前,特意查了相关的资料.其实在Linux中,可以用将内存模拟为一个块盘的技术,叫RAM disk.这是一种模拟的盘,实质数据都是存放在内存中的.RAM disk虚拟内存盘可以在某些特定的内存式存储文件系统下结合使用,比如tmpfs,ramfs.关于tmpfsd百度百科链接点此.通过此项技术,我们就可以将机器内存利用起来,作为一个独立的虚拟盘供DataNode使用了.

HDFS的内存存储流程分析


下面阐述的将是本文的核心内容,就是HDFS内存存储的主要过程操作.不要小看这仅仅是一个单一的StoragePolicy,里面的过程可并不简单,在下面的过程种,我会给出比较多的过程图的展示,帮助大家理解.

HDFS文件内存存储设置


要想让文件数据存储到内存中,一开始你要做的操作就是设置此文件的存储策略,就是上面提到的LAZY_PERSIST,而不是使用默认的StoragePolicy.DEFAULT,默认策略的存储介质是DISK类型的.设置存储策略的方法目前有2种:

  • 第一种,通过命令行的方式,调用如下命令
hdfs storagepolicies -setStoragePolicy -path <path> -policy LAZY_PERSIST

方便,快速.

  • 第二种,通过调用对应的程序方法,比如调用暴露到外部的create文件方法,但是得带上参数CreateFlag.LAZY_PERSIST.例子如下:
FSDataOutputStream fos =
        fs.create(
            path,
            FsPermission.getFileDefault(),
            EnumSet.of(CreateFlag.CREATE, CreateFlag.LAZY_PERSIST),
            bufferLength,
            replicationFactor,
            blockSize,
            null);

上述方式最终调用的是DFSClient的create同名方法,如下:

  /**
   * Call {@link #create(String, FsPermission, EnumSet, boolean, short,
   * long, Progressable, int, ChecksumOpt)} with <code>createParent</code>
   *  set to true.
   */
  public DFSOutputStream create(String src, FsPermission permission,
      EnumSet<CreateFlag> flag, short replication, long blockSize,
      Progressable progress, int buffersize, ChecksumOpt checksumOpt)
      throws IOException {
    return create(src, permission, flag, true,
        replication, blockSize, progress, buffersize, checksumOpt, null);
  }

方法经过RPC层层调用,经过FSNamesystem,最终会到FSDirWriteFileOp的startFile方法,在此方法内部,会有设置的动作

  static HdfsFileStatus startFile(
      FSNamesystem fsn, FSPermissionChecker pc, String src,
      PermissionStatus permissions, String holder, String clientMachine,
      EnumSet<CreateFlag> flag, boolean createParent,
      short replication, long blockSize,
      EncryptionKeyInfo ezInfo, INode.BlocksMapUpdateInfo toRemoveBlocks,
      boolean logRetryEntry)
      throws IOException {
    assert fsn.hasWriteLock();

    boolean create = flag
  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值