ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

HDFS数据分层存储策略详解:从冷热分离到Mover迁移实践

HDFS数据分层存储策略详解:从冷热分离到Mover迁移实践 做大数据这些年我越来越觉得很多团队对 HDFS 的理解停留在“能存、能读”的层面。数据量小的时候无所谓一旦集群上了规模、单日新增几个 TB 甚至几十 TB冷数据热数据全混在一起成本和性能的矛盾就会越来越尖锐。今天要聊的 HDFS 数据分层存储策略就是解决这个矛盾的一把钥匙。它不复杂也不需要额外引入一堆组件但对集群的稳定性、成本和访问效率的影响非常直接适合每一个正在维护生产集群、或者准备设计存储方案的工程师参考。1. 为什么数据分层存储是大数据团队的刚需1.1 冷热数据混存的代价先讲一个我见过的真实场景。某个团队的 HDFS 集群有 30 个数据节点清一色机械硬盘总共大概 2PB 容量。他们的业务很典型每天从业务库同步增量数据落一份原始日志到 HDFS然后用 Hive 跑离线分析最后把结果同步到 MySQL 或者 Redis。集群跑了一年以后问题开始一点点冒出来。首先是成本。他们为了支撑每天的写入和近期的分析查询所有节点都买的 4TB 大容量机械盘单节点存储成本不算高但架不住总量大。更头疼的是很多数据三个月前生成之后就再也没有被读过这些数据占据了超过六成的容量却仍然和热数据一样占着同等“贵”的存储资源。其次是性能。因为所有数据都在同一个存储池里当集群里面有大批任务在扫描历史数据时磁盘 IO 会被大量占用直接拖慢当天新增数据的写入和查询速度。这就是典型的冷热数据相互干扰。这个问题本质上不是“磁盘不够用”而是数据在生命周期不同阶段的需求不同。新鲜的数据需要高频读写用性能好的存储介质才划算老化之后的数据只求“放着别丢、偶尔翻出来用”用低成本的大容量介质才是正解。如果不做区分集群就是在不断地用高成本换取低收益。1.2 分层存储到底解决什么HDFS 分层存储的核心思路是把不同访问频率的数据放到不同性能等级的存储介质上。这个思路在传统存储领域其实早有应用比如存储阵列里的缓存层、性能层、容量层只是 HDFS 把它下沉到了分布式文件系统层面让数据块可以在节点之间、不同介质之间按策略自动流转。具体来说它解决三件事。第一件事是成本优化。把访问频率低的数据转移到 ARCHIVE 归档盘或者大容量低成本磁盘上把热数据保留在 SSD 甚至内存盘上同样的容量预算能装下的数据量完全不同。第二件事是性能隔离。热数据的读写请求被限制在高速介质上不会被冷数据的大量扫描拖累。第三件事是数据生命周期的自动化管理。不需要人为定期去判断“这份数据该不该删”而是靠存储策略和数据块搬运机制自动把数据放到合适的位置。从团队协作的角度看分层存储还有一个额外的好处它把“存储规划”这件事从拍脑袋变成了可配置、可审计的工程实践。数据落在什么介质上、什么时候触发迁移、迁移到哪个层级都有明确的规则和记录出了问题也能追溯。2. HDFS 分层存储的核心机制解析2.1 四种存储类型到底怎么选HDFS 的存储类型分为四种RAM_DISK内存盘、SSD固态硬盘、DISK普通机械硬盘和 ARCHIVE归档存储。这个概念比较好理解但很多人容易忽略一个关键点这些类型并不是 HDFS 自己定义的虚拟概念而是需要你在数据节点的配置里把实际挂载的磁盘目录“声明”为对应的存储类型。举个例子一台数据节点上有两块 SSD、三块机械硬盘。你可以在hdfs-site.xml里通过dfs.datanode.data.dir指定目录并用[SSD]、[DISK]这样的标记来声明目录类型。类似这样property namedfs.datanode.data.dir/name value[DISK]file:///data/hdfs/disk1,[DISK]file:///data/hdfs/disk2,[SSD]file:///data/hdfs/ssd1,[SSD]file:///data/hdfs/ssd2/value /property这里有个注意点一个物理磁盘上的多个分区最好不要混标成不同类型否则 DataNode 在做块放置时可能会把同一块物理盘既当 SSD 又当 DISK导致后续的迁移判断失真。另外ARCHIVE 类型通常对应的是专门的冷存储节点可以是低成本的大容量机械盘甚至是可拔插的归档介质。生产环境里最常见的是 DISK 和 ARCHIVE 的组合SSD 则根据预算和热点数据的规模酌情配置。RAM_DISK 在常规生产环境里用得不多因为它本质上依赖 DataNode 进程所在的机器内存一旦节点重启数据就没了。除非你的业务对延迟极其敏感、并且有完善的副本机制兜底否则不建议把重要数据放在这一层。2.2 存储策略与数据块放置的逻辑有了存储类型还需要定义“哪类数据放哪层”。HDFS 提供了若干预定义的存储策略比如HOT、COLD、WARM、ALL_SSD、LAZY_PERSIST等。每个策略包含两部分创建文件和写入数据块时使用的初始存储类型以及数据块被复制或迁移时希望达到的存储类型列表。以最常用的HOT策略为例它要求所有副本都放在DISK上COLD策略则要求所有副本放在ARCHIVE上WARM策略比较灵活允许一个副本在DISK、其余副本在ARCHIVE。这套机制的关键在于策略是文件或目录级别的属性可以随时调整。你今天把一个目录设成HOT明天改成COLD系统不会立刻把文件挪走而是等下一次数据块复制或迁移任务触发时再按新策略执行。这就引申出一个很多人踩过的坑改了目录策略之后发现数据并没有马上移动于是怀疑功能没生效。实际上HDFS 的策略生效是“异步”的必须运行数据迁移工具或者等待 DataNode 后台的复制线程才会真正把块从 DISK 搬到 ARCHIVE。理解这一点你在排查问题的时候就不会白着急。2.3 分层存储与传统存储分层有什么不一样有人会问这不就是存储阵列里的自动分层吗确实有相似之处但 HDFS 的分层有几个显著差异。第一HDFS 的分层是文件系统级别的而不是块设备级别的。它对上层应用透明Hive、Spark、Flink 这些组件完全无感知不需要改 SQL 或业务代码。第二HDFS 的副本机制让“数据温度”的判断可以更灵活。同一份数据可能有多个副本你可以让一个副本留在高速介质上服务实时查询其他副本放到归档介质上节约成本这在传统存储里很难做到。第三HDFS 的数据迁移是显式触发的你可以控制迁移窗口避开业务高峰。理解了这些机制再去看配置和操作思路会清晰很多。3. 实操HDFS 数据分层存储的配置与管理3.1 环境版本要求和前置检查先说版本。分层存储功能在 Hadoop 2.6.0 之后逐步成熟到 2.7.x、3.x 已经比较稳定。我个人的建议是生产环境至少用 Hadoop 3.x除了分层存储本身副本策略、纠删码等功能也更完善操作系统的兼容性也更好。动手之前先做几个前置检查确认所有 DataNode 节点的磁盘挂载信息确定哪些目录是 SSD、哪些是 DISK、哪些可以作为 ARCHIVE。检查hdfs-site.xml里的dfs.datanode.data.dir配置是否正确最好在滚动重启 DataNode 之前就把目录类型标记好。确认 NameNode 的 HA 状态正常避免在配置期间发生主备切换。确认有足够的临时空间存放迁移过程中的中间副本某些迁移操作会触发复制磁盘空间不够会导致任务失败。这里我有一个经验千万不要在业务高峰期刚配置完就立刻跑全量迁移。最好先在测试目录上验证策略生效再逐步扩展到正式数据。3.2 一步步完成存储类型声明假设我们有三个 DataNode 节点每个节点挂载了两块 1TB SSD 和四块 4TB 机械盘。我们的目标是SSD 用于热数据机械盘中的两块用于常规 DISK 数据另外两块用于 ARCHIVE 归档数据。在每台 DataNode 的hdfs-site.xml里修改dfs.datanode.data.dir大致如下property namedfs.datanode.data.dir/name value [SSD]file:///data/ssd1, [SSD]file:///data/ssd2, [DISK]file:///data/disk1, [DISK]file:///data/disk2, [ARCHIVE]file:///data/archive1, [ARCHIVE]file:///data/archive2 /value /property修改完成后需要滚动重启 DataNode 使配置生效。重启完成后用hdfs dfsadmin -report查看节点信息。如果配置正确每个 DataNode 的 Storage 信息里应该能分别看到 SSD、DISK、ARCHIVE 的容量统计。这一步是很多问题的源头如果你发现某个目录没有被识别成预期的类型优先检查路径权限、磁盘挂载方式以及 XML 标签是否写错。3.3 创建和设置存储策略存储策略在 NameNode 上管理。系统自带了几种预定义策略但生产环境有时候需要根据业务自定义。比如我们需要一个“双副本一个在 SSD一个在 DISK”的策略可以这样创建hdfs storagepolicies -createPolicy -policyName TWO_COPY_SSD_DISK -storageTypes SSD,DISK -replication 2创建完成后把这个策略应用到某个目录hdfs storagepolicies -setStoragePolicy -path /user/warehouse/ads -policy TWO_COPY_SSD_DISK这里要注意-setStoragePolicy设置的路径可以是目录也可以是文件。对目录设置后新创建的文件默认继承该策略已有文件不会自动迁移需要靠后续的迁移任务处理。查看某个路径当前的策略hdfs storagepolicies -getStoragePolicy -path /user/warehouse/ads查看集群所有策略hdfs storagepolicies -listPolicies关于自定义策略我补充一个实操细节策略名称不要用太随意的命名建议包含存储层信息和副本数信息比如WARM_1D_1A表示一个 DISK 副本加一个 ARCHIVE 副本。命名规范在后期运维时非常有用不然满屏的policy1、policy2没人分得清谁是谁。3.4 用 Mover 让数据“动”起来策略设置好之后重头戏是数据迁移。HDFS 自带的迁移工具叫mover它有两种工作模式。第一种是全量模式会扫描所有策略不匹配的块并尝试迁移hdfs mover -p /path/to/check第二种是基于时间的模式可以限制迁移任务在指定时间窗口内执行。生产环境我最推荐的方式是结合计划任务在凌晨低峰期跑迁移。比如这样写一个 Cron 任务0 2 * * * hdfs mover -p /user/warehouse 21 /var/log/hdfs/mover.logmover 执行过程中会在 NameNode 上生成迁移计划DataNode 之间开始复制和删除块。这里要注意迁移过程会占用一定的网络带宽和磁盘 IO。所以计划任务的时间窗口要预留足够的余量避免和前一天的凌晨任务比如全量导出重合。迁移完成后可以用下面的命令验证块的分布是否符合预期hdfs fsck /user/warehouse/ads -files -blocks -locations这个命令会列出每个文件的所有块及所在节点你可以在输出里看到DISK、ARCHIVE、SSD的分布比例判断迁移是否执行到位。4. 生产环境中的策略选型与最佳实践4.1 典型场景日志数据怎么分层日志类数据是分层存储最典型的受益者。假设我们有一个日志平台每天产生 10TB 的访问日志保留 90 天。前 3 天的日志需要支持实时检索和排障第 4 天到第 30 天的日志偶尔会被数据分析任务读取第 31 天之后的日志基本只用来做历史审计。在这个场景下我的建议是这样配置数据范围存储策略存储层原因最近 3 天HOT或 ALL_SSDSSD/DISK高频访问读延迟敏感第 4-30 天WARMDISK ARCHIVE低频访问保留性能余量第 31-90 天COLDARCHIVE仅审计需要成本优先具体操作是把日志根目录按天建子目录每天早上对超过 3 天的目录执行hdfs storagepolicies -setStoragePolicy改为WARM对超过 30 天的目录改为COLD然后再跑一次 mover。这个流程完全可以通过 Shell 脚本 Cron 实现不需要人工干预。关键点不要把策略生效的周期设置得太短。我遇到过有人每小时改一次策略、每小时跑一次 mover结果集群一半的带宽都耗在搬数据上业务任务全被拖慢。数据迁移的粒度按天、甚至按周来控制就够了。4.2 数据仓库表的分层策略设计数仓场景比日志场景更复杂一点。ODS 层、DWD 层、ADS 层的访问模式和生命周期差异很大不能一刀切。ODS 层是原始数据单表数据量最大但分区一旦写入就很少被更新。我的习惯是最近 7 天用HOT策略超过 7 天的分区直接转COLD不需要中间的WARM过渡。原因是 ODS 层基本只做一次性读取偶尔的补数任务再单独恢复分区策略即可。DWD 层是清洗后的明细数据访问频率比 ODS 高分析任务可能会反复扫描。建议最近 30 天用WARM更早的数据转COLD。但要注意如果业务上有针对历史分区的例行重跑任务比如每月跑一次上个月的全量统计那就要确保重跑任务的窗口内相关分区的数据不会因为迁移而降低读取性能。ADS 层是应用汇总数据数据量小、访问频率极高。我倾向于把所有 ADS 表都设置为ALL_SSD策略。原因很简单ADS 层的数据量通常只有几 GB 到几十 GB占用不了多少 SSD 空间但查询频率非常高用 SSD 带来的收益非常明显。4.3 和 Hive、Spark 等组件搭配的注意点分层存储在组件层面的感知非常弱Hive 里的表还是那张表Spark 读文件还是那样读。但有三个细节值得留心。第一Hive 的COMPACTION压缩合并操作会产生新文件新文件会继承所在目录的存储策略。如果你把表的某个分区改成COLD后续的 compaction 可能会把合并后的文件也放到ARCHIVE上这是正常行为但如果你希望 compaction 后的文件回到HOT就必须在任务前显式设置策略。第二Spark 的INSERT OVERWRITE或者TRUNCATE会删除旧目录并创建新目录如果新目录没有继承到正确的存储策略数据可能会落在默认的HOT策略下。所以凡是跑完写任务我建议都检查一下目标目录的策略是否符合预期。第三Flink 写 HDFS 时如果使用了分桶或者分区目录结构注意不要把策略设置在动态分区路径上。优先设置到稳定的父目录比如/user/warehouse/ods.db/ods_log_di避免每个分区临时去设置策略造成的额外开销。5. 常见问题与排查技巧实录5.1 异构存储节点配置后 DataNode 不识别现象修改dfs.datanode.data.dir后执行hdfs dfsadmin -report存储类型没有变化或者新目录始终显示为DISK。排查思路先看 DataNode 日志确认配置加载是否正常。最常见的原因是 XML 格式写错了比如中文字符、多余空格、标签未闭合。另外一个隐蔽原因目录权限不对DataNode 进程没有权限访问该目录会直接把目录标记为“failed”而不会报错退出。解决检查目录属主是否hdfs执行chown -R hdfs:hadoop /data/archive1等操作修复权限再重启 DataNode。可能原因判断方法处理方法XML 标签错误查看hdfs-site.xml是否合法检查标签闭合和类型标记目录权限不足ls -ld检查属主权限递归修改属主DataNode 未滚动重启查看启动时间滚动重启磁盘扇区异常dmesg查看 IO 错误更换磁盘后重新挂载5.2 数据迁移任务跑完但块没有搬走现象mover 任务正常结束日志里也显示执行成功但fsck查看块的分布发现数据仍然在原来的存储层。排查思路这个问题的原因通常是策略没有正确设置到文件所在的目录。注意setStoragePolicy的路径需要精确匹配文件的父目录。如果你对/user/warehouse/ads设置了策略但文件实际路径是/user/warehouse/ads/2024/01/part-xxx在 HDFS 的策略继承机制下子目录默认继承父目录策略但如果子目录本身被设置过其他策略父目录的修改就不会生效。解决用hdfs storagepolicies -getStoragePolicy -path 子目录查看子目录策略将其改为目标策略或者删除子目录的自定义策略然后再跑 mover。另外一个常见情况是数据块有多个副本其中某些副本所在节点不支持目标存储类型比如集群里根本没有挂载 ARCHIVE 目录的节点那么迁移任务会跳过不满足条件的块。这种情况需要检查集群是否真的规划好了归档节点。5.3 mover 运行缓慢占满带宽现象mover 运行期间集群的写吞吐量下降明显任务时间拉长。原因mover 默认会以较高并发进行块复制。集群规模小的时候DataNode 之间复制数据和业务写入争抢带宽影响会被放大。解决调整 mover 的限速参数。在hdfs-site.xml中配置property namedfs.datanode.balance.bandwidthPerSec/name value10485760/value /property这里10485760表示 10MB/s可以根据集群带宽酌情调整。另外尽量把 mover 安排到业务低峰期叠加限速配置基本就不会对业务造成明显干扰。实操心得我通常会把带宽限制在集群总带宽的 20% 以内。比如万兆网卡的集群单节点限速 50MB/s这样既能让迁移在几个小时内完成又不会拖垮正常任务。5.4 策略设置后新文件落到错误存储层现象目录已经设置了COLD策略但新写入的文件仍然落在DISK上。排查思路先确认客户端使用的 Hadoop 版本。老版本客户端不认识新的存储策略字段时会按默认策略写数据导致目录策略形同虚设。这个问题在混合版本集群中时有发生。解决统一客户端版本至少保证和 NameNode 的大版本一致。如果短期无法升级需要在写入方显式指定策略或者通过定时任务对新增目录重新设置策略。这个问题的另一个触发因素是使用了不支持策略的写入工具比如某些老版本的 Flume 或 Kafka Connect 插件。它们走的是 HDFS 的create接口但没有携带策略信息。遇到这种情况只能靠事后修正策略和迁移来兜底。写在最后的一点个人体会分层存储这件事看起来是一个技术功能用起来却更像是一个存储策略管理的工程问题。我见过不少团队把精力花在选 SSD、调参数上最后发现最大的收益其实来自“把冷数据及时降级”这件朴素的事。跑过几次大规模迁移之后我个人最大的体会是策略设计要留出余量操作要尽可能自动化但自动化之前一定要先在测试目录上跑通全流程包括策略设置、迁移触发、结果验证。另外每次调整策略和跑完 mover 后我都会顺手执行一次hdfs dfsadmin -report和hdfs fsck -files -blocks -locations把存储分布的变化记到运维文档里。做久了你会发现这套流程真正帮你省下的不只是硬件成本还有排障时花的那些冤枉时间。
返回列表