怎么做 HDFS 的原地平滑缩容?

怎么做 HDFS 的原地平滑缩容?背景 当数据规模越来越大,存储成本也水涨船高。随着时间推移,数据热度分布往往呈 2⁄8 原则,即 80% 的访问集中在 20% 的数据上。对于那不经常访问的 80% 数据来说,使用多个 SSD 来存储

怎么做 HDFS 的原地平滑缩容?

背景

当数据规模越来越大,存储成本也水涨船高。随着时间推移,数据热度分布往往呈 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.lock
  • BP-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 文件做校验,这个文件是用来记录校验到哪个位置的。
  • 不难看出所有的数据文件都存在 finalizedrbw 里面,并且同一个 DataNode 上面不会存在相同 Block ID 的数据文件。因此完全可以通过迁移 blk 文件的方式来将一块磁盘上面的数据移动到另外一块磁盘上,然后在卸载此磁盘来达到缩容的目的。

缩容步骤

本文示例的 HDFS 是 CDH 5.16 版本,使用 ClouderaManager 管理集群。集群只有 3 个节点,每个节点有多块 SSD 盘,数据两副本,存储利用率很低,每个节点都可以卸载掉一块磁盘,但是无法使用前面两种常见的缩容方法,同时缩容过程要尽可能可能减小对线上服务的影响。

以下操作均是针对单一 DataNode 的操作,其他 DataNode 也需要按照以下步骤执行(可以适当并行)

  1. 选择磁盘。选择需要被卸载的数据盘和接收数据的数据盘,注意要确保接收数据的磁盘剩余空间够大于被卸载磁盘上的数据。这里假设:

被卸载磁盘:/dfs1,此磁盘上的 DataNode 数据目录:/dfs1/dfs/dn

数据接收盘:/dfs,此磁盘上的 DataNode 数据目录:/dfs/dfs/dn

  1. 第一次复制数据。从 dfs.data.dir 里面挑选出在被卸载磁盘上面的目录,然后将此目录全量拷贝到接收数据盘上,为了尽量减少对 IO 的占用,用 ionicersync 的方式拷贝数据,确保不阻塞高优先级的任务。
ionice -c 2 -n 7 rsync -au /dfs1/dfs/dn/ /dfs/shrink_temp/dn
  1. 需要保证数据都被拷贝过去了,所以需要将 DataNode 停掉。可以通过 ClouderaManager 界面关闭 DataNode。

  2. 第二次增量复制数据。重复步骤 2,将在步骤 2 和步骤 3 之间的新增数据增量更新到接收盘上。增量数据会比较少,估计能很快完成。

ionice -c 2 -n 7 rsync -au /dfs1/dfs/dn/ /dfs/shrink_temp/dn
  1. 合并目录。此时被卸载盘上的数据都已经复制到接收盘上,但是数据还在原来的文件夹里面。如果同一块磁盘上面有两个 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
  1. 通过 ClouderaManager 修改 dfs.data.dir 配置项,删除卸载磁盘上的数据目录。

  2. 通过 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✿)

原文地址:https://www.cnblogs.com/JuiceData/archive/2022/03/15/16009475.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/5434.html

(0)
上一篇 2023-05-09
下一篇 2023-05-09

相关推荐

  • 用Python实现数据可视化

    用Python实现数据可视化a href=”https://beian.miit.gov.cn/”苏ICP备2023018380号-1/a Copyright www.python100.com .Some Rights Reserved.

    2024-03-16
    89
  • Python中的staticmethod

    Python中的staticmethodPython是一种面向对象的编程语言,常常被用来编写大型项目和应用程序。在这些应用程序中,我们通常需要许多函数和方法来实现不同的功能。但是某些功能可能并不需要访问类的实例,对于这种情况,Python提供了staticmethod来实现这一目的。在这篇文章中,我们将会深入探讨Python中的staticmethod以及它的应用。

    2024-07-04
    60
  • PSU的GI升级,ERROR: This patch is not applicable to GI home.[亲测有效]

    PSU的GI升级,ERROR: This patch is not applicable to GI home.[亲测有效]对 grid 和 oracle 的 $ORACLE_HOME/.patch_storage 目录进行赋权,否则可能会报错: ERROR: This patch is not applicable t…

    2023-04-11
    136
  • 利用Python操作字典快速实现数据处理

    利用Python操作字典快速实现数据处理Python中的字典是一种无序的键值对集合,用{}括起来,其中每个键值对用冒号 : 分割,每个键值对之间用逗号 , 隔开。它的基本操作包括以下几种:

    2024-01-24
    112
  • 利用Python计算Sin(40)的值

    利用Python计算Sin(40)的值在Python中,计算Sin(40)可以使用math库中的sin函数,但是该函数的参数是以弧度为单位的。因此在计算Sin(40)之前,需要首先将40°转换成弧度。一个圆的周长是2π,因此一个角度所对应的弧度值可以计算如下:

    2024-03-27
    76
  • MySQL多实例_MYSQL8.0

    MySQL多实例_MYSQL8.0文中使用mysql5.7 版本实现多实例,端口为3306和3307。 1、多实例本质在一台机器上开启多个不同的mysql服务端口(3306,3307),运行多个mysql服务进程,这些服务进程通过不同

    2022-12-24
    151
  • SQL 谓词简介_sql 谓词

    SQL 谓词简介_sql 谓词学习重点 谓词就是返回值为真值的函数。 掌握 LIKE 的三种使用方法(前方一致、中间一致、后方一致)。 需要注意 BETWEEN 包含三个参数。 想要取得 NULL 数据时必须使用 IS NULL。

    2023-04-29
    138
  • Neo4j/cypher学习笔记与学习建议

    Neo4j/cypher学习笔记与学习建议简介 本笔记的主要内容是 cypher 查询语言的编写与使用。 笔记主要整理自w3cschool上的neo4j教程以及Neo4j中文网所提供的cypher中文文档,此外还包括少量从其他个人博客与官方手

    2023-04-14
    163

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注