关于数据库:怎么做-HDFS-的原地平滑缩容

32次阅读

共计 3259 个字符,预计需要花费 9 分钟才能阅读完成。

背景

当数据规模越来越大,存储老本也水涨船高。随着时间推移,数据热度散布往往呈 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
  2. 须要保证数据都被拷贝过来了,所以须要将 DataNode 停掉。能够通过 ClouderaManager 界面敞开 DataNode。
  3. 第二次增量复制数据。反复步骤 2,将在步骤 2 和步骤 3 之间的新增数据增量更新到接管盘上。增量数据会比拟少,预计能很快实现。

    ionice -c 2 -n 7 rsync -au /dfs1/dfs/dn/ /dfs/shrink_temp/dn
  4. 合并目录。此时被卸载盘上的数据都曾经复制到接管盘上,然而数据还在原来的文件夹外面。 如果同一块磁盘下面有两个 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
  5. 通过 ClouderaManager 批改 dfs.data.dir 配置项,删除卸载磁盘上的数据目录。
  6. 通过 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✿)

正文完
 0