怎么做 HDFS 的原地平滑缩容?
亲爱的编程学习爱好者,如果你点开了这篇文章,说明你对《怎么做 HDFS 的原地平滑缩容?》很感兴趣。本篇文章就来给大家详细解析一下,主要介绍一下容器、MySQL、数据库、运维,希望所有认真读完的童鞋们,都有实质性的提高。
背景
当数据规模越来越大,存储成本也水涨船高。随着时间推移,数据热度分布往往呈 2⁄8 原则,即 80% 的访问集中在 20% 的数据上。对于那不经常访问的 80% 数据来说,使用多个 SSD 来存储真是巨大的浪费,需要将冷数据迁移到其他存储成本更低的系统里。这时 JuiceFS 成了理想之选,成本下降 20 倍,同时又提供跟 HDFS 一样高性能的元数据能力(避免Metastore 遍历元数据时雪崩),大量扫描冷数据时也有很高的吞吐量。如果 80% 的数据转移到 JuiceFS 上来,整体成本可节省 90%。如果再给 JuiceFS 提供 适当的空间做缓存,还可以完整替换 HDFS (20% 的热数据通过 JuiceFS 管理的缓存盘来服务,也可以有极高的性能)。
2019 年里,我们就实施过几个这样的案例。当数据迁移到 JuiceFS 上之后,HDFS 容量降下来了,就需要做好缩容才能最终把存储成本降下来。扩容大家都做过,但是缩容很多人还不熟悉,下面我们就详细说说如何做好 HDFS 缩容,尤其是这个背景下的缩容。
三种缩容方案
第一种缩容方法,如果 DataNode 的节点数目比较多,并且允许缩减存储空间的同时缩减 CPU 和内存资源,则可以缩掉若干个 DataNode 节点,直接使用 HDFS 提供的 decommission。这是最常见的方法,缩减过程中涉及大量数据的跨节点迁移,会产生大量的内网流量可能影响线上负载,需要运维人员保持密切关注和手动调优,通常需要一两周的时间。如果集群只剩 3 个 DataNode 节点,或者上面的 CPU 或者 内存资源不能同步缩减时,就不能用这个方法了。
第二种缩容方法,即在保持 DataNode 节点数不变的情况下,缩减每个节点上的磁盘空间,可以修改 DataNode 上的
dfs.data.dir参数,删掉一个或者多个磁盘目录,然后等待 HDFS 自动补充副本。这个方法统一也会导致节点间的大量数据移动,会产生大量的内网流量可能影响线上负载,需要运维人员保持密切关注和手动调优,可能也需要一两周时间。此外,如果数据只有 2 副本,相对会比较危险,一旦删除一个磁盘目录时正好有节点出问题或者某块磁盘坏掉,极有可能造成数据缺失。
以上两种方法都会产生大量网络流量,可能影响线上服务,并且会增加丢失数据的风险。本文提供第三种方法,怎么在缩容的同时,尽量避免产生的内网流量影响线上工作负载,同时尽量减少缩容过程中数据丢失的风险。
方案分析
首先我们看一下 DataNode 在磁盘上的目录结构:
└── dn
├── current
│ ├── BP-847673977-192.168.0.120-1559552771699
│ │ ├── current
│ │ │ ├── dfsUsed
│ │ │ ├── finalized
│ │ │ │ ├── subdir0
│ │ │ │ │ ├── subdir1
│ │ │ │ │ │ ├── blk_1073742303
│ │ │ │ │ │ ├── blk_1073742303_1479.meta
│ │ │ ├── rbw
│ │ │ └── VERSION
│ │ ├── scanner.cursor
│ │ └── tmp
│ └── VERSION
└── in_use.lockBP-847673977-192.168.0.120-1559552771699
:这是块池目录,如果以 Federation 方式部署的时候,会有多个块池目录。dfsUsed
:保存的是磁盘的使用统计数据,每 10 分钟刷新一次。finalized
和 rbw 目录:这两个都是用于存储数据块的,finalized 放的是已经完成写入的数据块,rbw 是正在写入的数据块。每个数据块对应 2 个文件,blk 文件存放数据,另外一个以 meta 结尾的存放校验和等元数据。VERSION
文件:主要包含布局版本、集群 ID、DataNode ID、块池 ID 等信息。scanner.cursor
文件:DataNode 会定期的对每个blk
文件做校验,这个文件是用来记录校验到哪个位置的。- 不难看出所有的数据文件都存在
finalized
和rbw
里面,并且同一个DataNode
上面不会存在相同 Block ID 的数据文件。因此完全可以通过迁移 blk 文件的方式来将一块磁盘上面的数据移动到另外一块磁盘上,然后在卸载此磁盘来达到缩容的目的。
缩容步骤
本文示例的 HDFS 是 CDH 5.16 版本,使用 ClouderaManager 管理集群。集群只有 3 个节点,每个节点有多块 SSD 盘,数据两副本,存储利用率很低,每个节点都可以卸载掉一块磁盘,但是无法使用前面两种常见的缩容方法,同时缩容过程要尽可能可能减小对线上服务的影响。
以下操作均是针对单一 DataNode 的操作,其他 DataNode 也需要按照以下步骤执行(可以适当并行):
- 选择磁盘。选择需要被卸载的数据盘和接收数据的数据盘,注意要确保接收数据的磁盘剩余空间够大于被卸载磁盘上的数据。这里假设:
被卸载磁盘:
/dfs1,此磁盘上的 DataNode 数据目录:
/dfs1/dfs/dn
数据接收盘:
/dfs,此磁盘上的 DataNode 数据目录:
/dfs/dfs/dn
第一次复制数据。从
dfs.data.dir
里面挑选出在被卸载磁盘上面的目录,然后将此目录全量拷贝到接收数据盘上,为了尽量减少对 IO 的占用,用ionice
加rsync
的方式拷贝数据,确保不阻塞高优先级的任务。ionice -c 2 -n 7 rsync -au /dfs1/dfs/dn/ /dfs/shrink_temp/dn
- 需要保证数据都被拷贝过去了,所以需要将 DataNode 停掉。可以通过 ClouderaManager 界面关闭 DataNode。
第二次增量复制数据。重复步骤 2,将在步骤 2 和步骤 3 之间的新增数据增量更新到接收盘上。增量数据会比较少,估计能很快完成。
ionice -c 2 -n 7 rsync -au /dfs1/dfs/dn/ /dfs/shrink_temp/dn
合并目录。此时被卸载盘上的数据都已经复制到接收盘上,但是数据还在原来的文件夹里面。如果同一块磁盘上面有两个 DataNode 数据目录的话,会导致 HDFS 容量计算重复,因此需要合并。可以通过 rsync 的硬链的方式将数据拷贝过去,这样不涉及真正的数据拷贝,执行非常快,同时将拷贝过去的源数据删除。检查剩余数据是否有 blk 文件,没有就合并完成。
ionice -c 2 -n 7 rsync -au --link-dest=/dfs/shrink_temp/dn --ignore-existing --remove-source-files /dfs/shrink_temp/dn/ /dfs/dfs/dn
- 通过 ClouderaManager 修改 dfs.data.dir 配置项,删除卸载磁盘上的数据目录。
通过 ClouderaManager 启动 DataNode,并检查 HDFS 的状态。
sudo -u hdfs hdfs fsck /
为什么不直接将被卸载盘的数据复制合并到接收盘的 DataNode 数据目录里面呢? 这是因为,在第一次拷贝的时候,DataNode 仍然在运行,因此 DataNode 会定期检查副本数量,此时拷贝过去的数据算是额外副本,有可能会被 DataNode 删除掉。
整个缩容过程中 DataNode 停止的时间只是步骤 4 和步骤 5 所需时间。步骤 4 是增量拷贝,速度很快,步骤 5 只是文件元数据操作,同样很快。
以上步骤看起来比较多,手动操作会容易出错,因此我们将以上缩容过程写了一个脚本(部分操作依赖 Hadoop 发行版的 API,目前支持 CDH5),请下载setup-hadoop.py,运行命令,并按照提示输入进行缩容:
python setup-hadoop.py shrink_datanode
未来改进
在上面的缩容过程里,需要将数据是从一块磁盘完整地拷贝到另外一块磁盘,需要它有足够的剩余空间,另外也可能导致 DataNode 内磁盘间数据不均衡。未来可以改进下这个缩容过程,在复制数据时根据某个规则将 blk 文件复制到多块盘,确保多块磁盘之间的数据均衡。
如有帮助的话欢迎关注我们项目 Juicedata/JuiceFS 哟! (0ᴗ0✿)
文中关于mysql的知识介绍,希望对你的学习有所帮助!若是受益匪浅,那就动动鼠标收藏这篇《怎么做 HDFS 的原地平滑缩容?》文章吧,也可关注golang学习网公众号了解相关技术文章。
macOS Monterey 12.2 搭建 GO+PHP 开发环境
- 上一篇
- macOS Monterey 12.2 搭建 GO+PHP 开发环境
- 下一篇
- EEE6207
-
- 俭朴的溪流
- 太详细了,码起来,感谢up主的这篇技术文章,我会继续支持!
- 2023-02-28 16:01:05
-
- 霸气的黄豆
- 这篇文章真及时,好细啊,写的不错,已加入收藏夹了,关注up主了!希望up主能多写数据库相关的文章。
- 2023-02-24 20:22:06
-
- 无限的保温杯
- 受益颇多,一直没懂这个问题,但其实工作中常常有遇到...不过今天到这,帮助很大,总算是懂了,感谢博主分享博文!
- 2023-02-16 17:39:46
-
- 数据库 · MySQL | 1小时前 |
- MySQL 递归 CTE 遍历树数据时怎么防止无限循环
- 142浏览 收藏
-
- 数据库 · MySQL | 4小时前 |
- MySQL invisible index 如何安全观察索引下线影响
- 300浏览 收藏
-
- 数据库 · MySQL | 5小时前 | MySQL · 索引优化 · generated column · mysql 索引 优化器 生成列
- MySQL 生成列索引为什么没有被优化器使用
- 300浏览 收藏
-
- 数据库 · MySQL | 8小时前 |
- MySQL 窗口函数取每组最新记录时如何处理并列时间
- 242浏览 收藏
-
- 数据库 · MySQL | 9小时前 |
- MySQL JSON_VALUE 返回 NULL 时怎么区分缺少路径和空值
- 170浏览 收藏
-
- 数据库 · MySQL | 10小时前 | MySQL · JSON查询 · JSON_TABLE · SQL技巧 · mysql JSON_TABLE FOR ORDINALITY JSON数组序号
- MySQL JSON_TABLE 的 FOR ORDINALITY 怎么保留数组原始序号
- 139浏览 收藏
-
- 数据库 · MySQL | 13小时前 |
- MySQL 复制延迟升高时怎么区分 SQL 线程和 IO 线程
- 304浏览 收藏
-
- 数据库 · MySQL | 15小时前 | MySQL事件 · 事件调度器 · 任务表排查 · mysql 定时任务 CREATE EVENT Event Scheduler INFORMATION_SCHEMA.EVENTS
- MySQL 事件调度器执行了但任务表没有更新怎么排查
- 486浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 47次使用
-
- SuperCLUE
- SuperCLUE是权威的中文大语言模型综合评测基准,涵盖语言理解、知识应用、AI Agent智能体及安全性等12项核心能力。通过多轮对话与客观测试,定期发布榜单与技术报告,为模型研发、优化及行业选型提供科学依据。
- 198次使用
-
- C-Eval
- 深入了解C-Eval中文评估套件,涵盖52个学科与4级难度。本文详解其功能特点、Zero-shot/Few-shot使用方法及代码示例,助您全面评测LLM中文理解与泛化能力。
- 133次使用
-
- AI Prompt Library
- 探索AI Prompt Library免费资源库,涵盖营销、写作及多场景AI提示词。兼容ChatGPT、Claude等工具,一键复制优化输出,提升工作效率。
- 67次使用
-
- Generrated
- Generrated汇集9300+张DALL·E生成图像及对应提示词,支持查看完整图集、对比DALL·E 2与3版本差异,是AI绘图新手学习Prompt设计与获取创作灵感的实用工具。
- 47次使用
-
- MySQL 明明加了索引,为什么查询还是很慢?先查这 6 个点
- 2026-06-27 374浏览
-
- 接口返回的数据和数据库不一致怎么办?按数据生命周期排查
- 2026-06-27 398浏览
-
- golang MySQL实现对数据库表存储获取操作示例
- 2022-12-22 499浏览
-
- golang 基于 mysql 简单实现分布式读写锁
- 2023-01-07 384浏览
-
- 详解如何利用GORM实现MySQL事务
- 2023-01-07 184浏览
