HDFS-Tiering 数据分层存储

Posted 小米技术

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDFS-Tiering 数据分层存储相关的知识,希望对你有一定的参考价值。

1. 背景




随着小米业务迅猛发展,存储到 HDFS 集群的数据量不断增大,存储成本也不断攀升。尤其是海外 HDFS 集群每 GB 数据的成本是国内集群的 10 倍左右,如何优化海外集群的存储成本变得非常迫切。海外 HDFS 集群主要采用云主机挂载 EBS 的方式搭建,EBS 是成本的大头。但 EBS 可靠性高,性能优良,又是业务正常运行的保障。
经过我们对 HDFS 元数据信息的分析,以印度离线集群为例,发现半年以上没有访问的冷数据大约占 25% 左右。这些数据存储在高性能高成本的 EBS 上是一种浪费,是否可能把这部分冷数据存储到更便宜的存储介质上?答案是肯定的。

Amazon S3(0.021$/GB.月)的单价不到 EBS(0.051$/GB.月)的一半,可靠性高,但访问速度慢,在我们测试环境里,挂载 S3 的盘读写速度只有 40MB/s 左右,只有 EBS 的 1/5。但考虑到冷数据的读写频率比较低,存储到 S3 上是可行的,这样冷数据的存储成本可以下降一半多。依赖 S3 自身 11 个 9 的持久性,我们可以只保存一个副本,这样对原来三备份的冷数据的成本可降低到 1/6。同样,对于国内的集群,也有性能稍差但价格便宜的高密度机型可以选择,可以采用同样的方案来保存冷数据。

经过调研和分析,在上层应用无感知、HDFS 集群系统性能无明显下降的前提下,为降低存储成本,我们需要把数据按冷热进行分层管理,不同类型的数据存储到不同的存储介质上。

HDFS 社区版是支持数据分层存储的,可把不同的存储介质设置成不同的存储类型(Storage Types),支持的存储类型有5种:RAM_DISK、SSD、DISK、ARCHIVE、PROVIDED。把不同的数据设置成不同的存储策略(Storage Policies),支持的策略有7种:Hot、Warm、Cold、All_SSD、One_SSD、Lazy_Persist、Provided。默认 Storage Policies 是 Hot,可通过系统命令或者 API 改变数据的属性。

但 HDFS 社区版存在以下问题:
  • 对存量数据处理的支持不好。设置数据的 Storage Policies 属性后,只对新写入的数据有效。对于存量数据,系统并不能将其自动移动到对应的存储介质上。HDFS 提供了一个外置工具 mover,可以把数据移动到正确的位置,但 mover 也不能确保调用后会把所有的数据都移动过去。

  • 没有提供冷数据分析方案。

  • 没有提供把远程存储设备(譬如 S3)mount 到 DataNode 上作为存储类型的方案。


2. 实现




小米 HDFS-Tiering 方案简化了 HDFS 社区版的存储类型和存储策略,实现了冷热数据的自动分层管理,不同类型的数据存储到不同存储介质上。
主要解决了以下问题:
  • 把远程的廉价存储介质挂载到 DataNode 作为 Archive 类型卷。

  • 自动分析集群数据,获得冷数据列表,改变数据的 Storage Policies 属性。

  • 自动循环调用 mover 工具,移动冷数据,并利用 fsck 命令判断数据是否迁移完成。

  • 支持在可靠存储介质上实现文件级别的 Dedup。

  • 支持灵活的存储配置方案,可切换 Archive 类型卷对应的存储介质。


小米 HDFS-Tiering 方案把存储介质分成两种类型:
  1. DISK:普通存储介质,譬如 HDD/SSD 本地硬盘、EBS 网盘等。

  1. ARCHIVE:低速廉价存储介质,譬如S3存储、高密度硬盘、磁带存储等。


又把数据分成三种存储策略,实现了数据在三种策略之间的自动转换(如图 2.1 所示):
  • HOT:三副本都在 DISK 上。

  • WARM:一副本在 DISK,两副本在 ARCHIVE 上。

  • COLD:三副本都在 ARCHIVE 上。


                         
图 2.1 数据类型转换

以下介绍各主要模块的实现细节。
2.1 挂载远程存储设备到 HDFS 系统
为了尽可能复用现有的 HDFS 框架,我们采取把远程存储设备挂载到 DataNode 本地的方案,这样DataNode 就可把远程盘当作本地盘一样处理。对于 Amazon S3 的访问,小米已有自研的 FDS 方案。通过 FDS 访问 S3,再通过 FDS-FUSE 工具挂载 FDS 到本地目录。

FDS(File Storage Service):小米自研的对象存储服务,对象的 Meta 信息存储在 HBase 里,数据可配置不同的存储介质。这里我们配置的是 Amazon S3,将来可配置成其他存储设备,如金山云的 KS3 等。通过 FDS 这层可以屏蔽不同存储介质的差异。

FDS-FUSE:小米自研的用户态基于 FUSE 的 POSIX 文件系统工具,可把远程 FDS mount 到本地,使得 HDFS 访问远程存储就像访问本地磁盘一样。

如图 2.2 所示,远程的廉价存储介质 S3 挂载到 DataNode 上,作为 Archive 类型卷。通过 FDS-FUSE 把 FDS mount 到 DataNode 本地,FDS 把 S3 作为数据存储设备。这样在 DataNode 上就看到一个由远程 mount 过来的目录,添加这个目录到 DataNode 配置文件作为 Archive 类型卷,DataNode 就可以写数据到远程的存储介质 S3 上了。

对于高密度机器类型的本地存储,就不需要 FDS 和 FDS-FUSE,直接把高密度机器的盘配置成 Archive 类型卷就可以了。

HDFS-Tiering 数据分层存储
图 2.2 DataNode 部署远程 Archive Volume

2.2 Auto-Tiering 自动数据分析与移动
Auto-Tiering 可自动周期性地分析集群中的所有数据,根据文件的访问频率对数据进行分层,并把分层信息设置到数据的属性里,然后循环触发系统 mover 操作,把不同层次的数据移动到对应的存储介质上。整个系统包括 Image 分析服务、Mover 服务和 Tiering 服务三部分,这三个服务都可以独立部署在不同的机器上。三个服务和 NameNode 之间的关系如图2.3 所示。
HDFS-Tiering 数据分层存储
图 2.3 Auto-Tiering 主要模块和 NameNode 的关系

Image 分析服务(冷数据分析): 为减少遍历整个文件系统对 NameNode 的压力,Auto-Tiering 通过分析集群 Meta 信息快照(fsimage 文件)的方式获得集群上所有的文件信息。由于分析 HDFS 的 fsimage 文件需要大量内存(实际大约需要 fsimage 文件大小两倍的内存),所以独立出来这个服务,和具体的集群没有关系,可同时为多个 Tiering 服务提供 fsimage 文件读取分析服务,并返回分析结果文件。Image 分析服务会读取 fsimage 文件,遍历集群上所有的文件信息,并按用户设置的策略生成冷数据文件列表。冷数据文件列表中包括 WARM 文件列表和 COLD 文件列表,如果有冷数据需要被重新设置成热数据,还会同时生成 HOT 文件列表。

Mover 服务: 根据 Image 分析服务的结果,循环运行 mover 命令,遍历设置过 Storage Policies 属性的文件列表,触发数据迁移,把数据存储到对应的存储介质上。并根据 HDFS 系统命令 fsck 查看是否移动完成,如果移动完成则从文件列表里删除。循环执行该过程,直至列表里所有文件都被移动到正确的存储介质上,然后删除文件列表。数据移动流程如图 2.4 所示。
                         HDFS-Tiering 数据分层存储
图 2.4 数据移动流程

Tiering 服务:协调 Auto-Tiering 的整个过程,和具体的集群相关。一个 HDFS 的 Namespace 对应一个 Tiering 服务,用户可根据不同集群的要求做不同的配置,周期性启动服务。Tiering 服务会根据用户的配置向 Image 分析服务提交分析请求,并根据返回的结果启动 MR Job,访问对应的 HDFS 系统,设置对应文件的 Storage Policies 属性。

用户可设置选项主要有:
  • hdfs.tiering.interval:两次服务启动的间隔。

  • hdfs.tiering.dirs:需要做 Tiering 的根目录。

  • hdfs.tiering.file.time.window.ms:冷数据的判断条件,默认是6个月没有访问的 HOT 文件认为是 WARM 文件,6个月没有访问的 WARM 文件认为是 COLD 文件。


    2.3 FDS 数据 Dedup
    由于 Amazon S3 是可靠的存储设备,再存储三备份已没有必要。在不改变现有 HDFS 架构的前提下,我们在 FDS 层面做文件级别的 Dedup。三备份的文件存储在 HDFS 的三个 DataNode 上,在FDS 上会有三条文件信息。但由于文件内容相同,通过 Dedup 后,实际存储到 S3 存储上只有一个文件,如图 2.5 所示。
                               HDFS-Tiering 数据分层存储
    图 2.5 数据块 Dedup

    2.4 HDFS 扩展
    为了支持低速且不稳定的远程 Volume 在 HDFS 系统中正常的工作,针对实现过程中遇到的各种问题,我们对现有的 HDFS 系统做了以下扩展。

    1、支持跨 DataNode 的 Link Block 功能

    问题描述:HDFS 系统中挂掉一台 DataNode 是经常的,需要把挂掉的机器上 Block 复制到其他机器。对存储在远程的 Archive 类型 Block 来说复制过程非常慢,数据量大时,还会引起复制高峰,FDS 或 S3 都有可能被打满,引起系统卡顿,同时其他 DataNode 对 Archive Block 读写也会卡住,造成更多DataNode 假死,引起连锁反应。而且,对 S3 的不必要读写也会产生额外费用。

    优化方案:正常的 DataNode 之间的数据块复制如图 2.6 所示,源 DataNode1 需要通过 FDS 从远程 S3读出数据,通过网络发送到目标 DataNode2,DataNode2 再把从 DataNode1 接收到的数据通过 FDS 写到远程的 S3 上,完成一个块的复制。

    由于 FDS 上已经支持文件级别的 Dedup 功能,一个块的三个备份实际上都指向 S3 上的一个文件。我们在 DataNode 之间添加了一个 linkBlock IPC 调用,实现针对 FDS 块的快速复制方法。如图 2.7 所示, DataNode1 没有真正的通过 FDS 从远程 S3 上读取数据,而是把块的存储信息(文件名称、位置等)发到到目标 DataNode2,DataNode2 根据收到的块的存储信息直接在 FDS 上添加一个对原块的引用,完成块的复制,避免了块复制过程中对 S3 的访问,整个过程没有发生实际的数据移动,类似文件系统的 Hard Link 功能。

                              HDFS-Tiering 数据分层存储
    图 2.6 DataNode 之间正常块复制数据流

                             
    图 2.7 DataNode 之间通过 Link Block 复制块操作

    2、添加 DataNode 的 Block 信息缓冲功能

    问题描述:由于 FDS 上对象的 Meta 信息存储在 HBase 里,是扁平的 KV 结构,没有树型结构的概念,造成目录遍历非常耗时。DataNode 启动需要遍历整个数据目录下的 Block 文件,解析并加载到到内存。这就造成挂载远程 FDS S3 卷的 DataNode 启动速度非常慢,由原来的几十秒增加到几个小时。

    优化方案:添加 DataNode Cache 功能,添加系统钩子,在关闭 DataNode 进程时把内存中的 Block 信息 Dump 到缓冲文件中,启动时不再遍历数据目录,而是直接从文件加载,极大的提高了 DataNode 的启动速度。后来发现把信息 Dump 到 FDS S3 卷上也太慢,数据量大时系统钩子函数还没执行完 DataNode 进程就退出了,于是又添加了支持 Dump 到普通盘的功能。最终启动速度降到了秒级别,比普通磁盘还快。这种 Cache 方案在社区最新版本中也有类似实现 (HDFS-7928 )。

    其他扩展参照表 2.8 :
    问题描述
    优化方案
    DataNode 进程偶尔会变僵尸进程,造成整个节点不可用。

    分析原因是 FDS-FUSE 在 DF 调用的时候会偶尔卡住。先减少 DF 的调用频率,对于固定大小的 Volume 也没必要每次心跳都调用 DF,改成只在 DataNode 启动的时候调用一次 DF 并保存,心跳时复用保存的结果。
    如何监控 Archive 数据总量,分离 Archive 数据和普通数据。
    HDFS 2.6 的 NameNode 主页面添加显示 Archive 磁盘总量和已用量,在普通盘的用量中剔除 Achive 类型数据。
    由于 S3 读写速度慢,经常因为读写超时失败。
    增加 HDFS 针对 Archive 卷的读写延迟单独配置。
    下掉一个带 Archive 的 DataNode 的时候,由于需要把上面的数据复制到其他盘,过程非常慢。
    下节点的时候对 Archive 类型数据,只要副本数达到最低数就可下。
    有时候 FDS-FUSE mount失败,数据会写到本地磁盘上,造成数据混乱和丢失风险。
    加载 Archive 卷之前检查要 mount 的卷的 filesystem 是否存在。
    加载 Archive 卷之前检查要 mount 的卷的 filesystem 是否存在。
    添加配置,忽略读取存储在 Archive 卷上的块,因为 S3 读取慢而且访问需要费用,本身又有可靠性保障。
    由于远程盘稳定性差,DataNode 在收集 Archive 卷信息的时候有可能卡住一会,造成心跳信息不能及时的上传到 NameNode,造成假死现象。
    为 Archive 卷添加单独的心跳信息收集线程,如果卡住,可先用上次收集的
    批量带 FDS Volume 的 DataNode 死掉后,起不来,循环超时。
    原因是在修复 DataNode 内存中的块信息和磁盘上的差别时,如果差别太大,会卡住,造成假死。更新一定数量的差异后,添加 sleep 一下,释放锁,保证心跳信息正常发出。
    经常 Failed Volumes,遇到 FDS 动荡,FDS Volumes 大部分 Failed。只能重新启动 DataNode 才能恢复。
    由于远程盘不稳定,偶尔会出现读写错误,DataNode 会把它设为 Failed Volume,而且还没有加回机制。添加读写错误次数,对网盘达到一定的次数才认为 Failed Volume,添加错误盘的检查机制,如果它又变好了,可以再自动加回到系统当中。
    DataNode 在复制块时会组成一个 pipeline,同时复制多个,这对 FDS 的 Dedup系统造成混乱。
    对 Archive 块一次只复制一个,避免对 FDS 的冲击。
    网络盘偶尔会断开一会,经常会误报 missing block。
    对存储在 Archive Volume 的块,如果读失败,在上报 missing block 同时检查下 Archive Volume 的根目录是否存在,如果也不存在,说明 Archive Volume 暂时不可用,不上报。另外 DataNode 的 DirectoryScanner 也在底层定时扫描所有的快文件,如果正好遇到 Archive Volume 不可用,也会造成批量的 missing block,在上报前也采取相同的策略。
    无法判断 mover 是否正确的把数据从 Disk 移动到Archive Volume 上。
    为 fsck 添加显示 storage types 功能,支持检验位置和属性是否匹配。
    DataNode 统计 Archive Volume 容量时太耗时。
    DataNode 通过内存中的 Replica 信息定时统计已用容量,对块文件的大小直接可以从块文件里拿到,对于 Meta 文件来说由于是变化的,需要访问文件系统,这就造成了对 Archive Volume的频繁访问,修改成通过 checksum 计算出 Meta 文件的大小。
    表 2.8 支持远程慢速存储设备的 HDFS 扩展

    已合入到 HDFS 社区的相关 patch
    HDFS-15028: Keep the capacity of volume and reduce a system call
    HDFS-15033: Support to save replica cached files to other place and make expired time configurable
    HDFS-15039: Cache meta file length of FinalizedReplica to reduce call File.length()
    HDFS-15158: The number of failed volumes mismatch with volumeFailures of Datanode metrics
    HDFS-14993: checkDiskError doesn't work during datanode startup
    HDFS-15207: VolumeScanner skip to scan blocks accessed during recent scan peroid

    链接参考:https://issues.apache.org/jira/browse/HDFS-15028


    未合入到 HDFS 社区的相关 patch
    HDFS-15221: Add checking of effective filesystem during initializing storage locations
    HDFS-15188: Add option to set Write/Read timeout extension for different StorageType
    HDFS-15022: Add new RPC to transfer data block with external shell script across Datanode
    HDFS-15001: Automatically add back the failed volume if it gets better again

    3. 结果




    该系统已经在海外印度 HDFS 离线集群上线一年左右,经过大量 bug 修复及专门优化后,在数据持久化、可用性方面都表现良好,处理的冷数据最多达到 1.5PB,占集群总量的 20% 左右,每月可节约成本约 140 万元。

    在 Tiering 实施之前,存储在 EBS 上的 1.5PB 数据的每月成本(三副本,0.051$/GB.月):
    1.5×1024×1024×3×0.051$ = 240648.192$

    在 Tiering 实施之后,存储在 S3 上的 1.5PB 数据的每月成本(一副本,0.021/GB.月):
    1.5×1024×1024×0.021 = 33030.144$

    每月可节约成本:
    240648.192$-33030.144$ = 207618.048$ ≈ 20万美元 ≈ 140万元

    高密度机型作为 Archive Volume 的方案也已经测试通过,计划在国内 HDFS 集群上线。
    该系统还参加了小米集团 2019 年百万美金大奖的项目评审,并获得 Top 20 入围奖。

    参考链接




    [1]HDFS Storage Types and Storage Policies:https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/ArchivalStorage.html#Storage_Policies:_Hot.2C_Warm.2C_Cold.2C_All_SSD.2C_One_SSD.2C_Lazy_Persist_and_Provided
    [2]Amazon EBS 定价 https://aws.amazon.com/cn/ebs/pricing/
    [3]Amazon S3 存储类 https://aws.amazon.com/cn/s3/storage-classes/

    关于我们




    小米云平台部门存储团队,负责为小米集团各业务线提供可靠、易用、低成本的存储服务,涵盖分布式文件系统、对象存储、表格存储、KV存储、关系数据库、OLAP系统、时序数据库、图数据库、缓存系统等。团队拥有非常好的技术氛围,积极拥抱开源,每年向 HDFS/HBase/Kudu 等 Apache 项目贡献大量 patch,且在 HBase/Kudu 项目上产出了多名 Committer/PMC member。
    团队在北京和武汉均有 open 职位,欢迎感兴趣的小伙伴加入,简历投递至:qinzuoyan@xiaomi.com 。


    「往期文章」


    以上是关于HDFS-Tiering 数据分层存储的主要内容,如果未能解决你的问题,请参考以下文章

    如何使用redis存储分层数据?

    在 Google App Engine 数据存储中存储分层数据?

    以高写入负载在 MySQL 中存储分层数据

    Windows server 存储池数据分层功能影响性能怎么办?

    存储系列之 总结:存储分层

    Mysql逻辑分层存储引擎