概述

DiskBalancer是一个命令行工具,可在DataNode的所有磁盘上均匀分发数据。  此工具对给定的DataNode进行操作,并将块从一个磁盘移动到当前DataNode的另一个磁盘。DiskBalancer通过创建计划并继续在DataNode上执行该计划。 计划是一组陈述,描述了两个磁盘之间应该移动的数据。 计划由多个移动步骤组成。 移动步骤具有源磁盘,目标磁盘和移动的字节数。 可以针对运行数据节点执行计划。DiskBalancer是一个相对独立的线程,它可以对数据的复制进行限流。 集群默认是启用DiskBalancer的, 不启用DiskBalancer 需要在hdfs-site.xml中将dfs.disk.balancer.enabled设置为false。

实现

Client端

执行磁盘均衡需要使用对应的HDFS命令,其实就相当于新起一个客户端生成对应DataNode磁盘均衡的信息。客户端磁盘均衡要经过三个阶段:Discover(发现)到Plan(计划),再从Plan(计划)到Execute(执行)。

hdfs 磁盘平衡命令 hdfs diskbalancer_数据

Discover阶段:

是通过计算各个节点内的磁盘使用情况, 然后得出需要数据平衡的磁盘列表.这里会通过磁盘使用密度(Volume Data Density)的概念作为一个评判的标准, 这个标准值将会以节点总使用率(totalused/totalcapacity)作为比较值.。举个例子,如果一个节点总使用率为75%,就是0.75。其中A盘使用率0.5(50%),那么A盘的volumeDataDensity密度值就等于0.75-0.5=0.25。同理,如果超出的话,则密度值将会为负数。于是我们可以用节点内各个盘的volumeDataDensity的绝对值来判断此节点内磁盘间数据的平衡情况,如果总的绝对值的和越大,说明数据越不平衡。

plan阶段:

命令:hdfs diskbalancer -plan datanode1

在指定plan阶段时你需要指定待磁盘均衡的DataNode节点。 plan阶段会拿到上一阶段的汇报结果数据然后会对指定的DataNode生成Plan。Plan并不是一个最小的执行单元,它的内部由Step组成。每个Step中会指定好源、目标磁盘以及从源移动数据大小等。这里的磁盘对象是一层经过包装的对象DiskBalancerVolume,并不是原来的FsVolume。

对于磁盘数据的迁移策略,HDFS仅仅支持 GreedyPlanner,其策略是不断地将数据从使用率最高的设备移动到使用率最少的设备,直到所有数据均匀地分布在所有设备上。用户还可以在使用 plan 命令的时候指定空间利用阀值-thresholdPercentage,也就是说,如果空间利用率的差异低于此阀值,planner 则认为此磁盘已经达到了平衡。

磁盘密度:磁盘密度 = DN存储使用百分比(当前DN存储数据大小/当前DN容量) - 当前磁盘存储使用百分比(当前磁盘存储数据大小/当前磁盘总容量)  

注:磁盘密度小于0的表示磁盘存储容量紧张,否则表示空闲 

如何确定磁盘需要块移动:在指定plan命令的时候可以指定一个阈值百分比-thresholdPercentage,默认10%。当磁盘密度大于或者小于DN存储使用百分比时表示需要块移动。

磁盘密度 < DN存储使用百分比

hdfs 磁盘平衡命令 hdfs diskbalancer_数据_02

 thresholdPercentage || 磁盘密度 > DN存储使用百分比 

hdfs 磁盘平衡命令 hdfs diskbalancer_数据_02

 thresholdPercentage


源磁盘需要移动数据大小

源磁盘可移动数据大小 =  源磁盘数据大小 -DN存储使用百分比 * 源磁盘数据大小

目标目录可接受数据大小 = 目标磁盘容量*DN存储使用百分比 - 目标磁盘使用量

可移动数据大小 = min(源磁盘可移动数据大小,目标目录可接受数据大小)

源磁盘与目标磁盘的选择:每次计算都会计算当前DN所有的可用的磁盘密度,然后找到其磁盘容量最紧张与磁盘容量最空闲的两个来进行数据复制

生成plan之后,DiskBalancer会将执行计划的内容以Json的格式输出存储在 HDFS 之上。在默认情况下,这些文件是存储在 /system/diskbalancer 目录下面,可以由-out参数指定。

大致流程: 

hdfs 磁盘平衡命令 hdfs diskbalancer_数据_04

 execute 阶段:

命令:hdfs diskbalancer -exceute /system/diskbalancer/datanode1.json

在Plan阶段,生成了对一个DataNode磁盘均衡的Plan,Plan包含多个Step。在execute 阶段就是将之前生成的Plan传递给对应的DataNode。执行其实就是通过clientDataNodeProtocol的submitDiskBalancerPlan方法将Plan传递给对应的DataNode,后续的就是DataNode处理此Plan。

DataNode端

DataNode执行磁盘均衡

在DataNode这一端在接受到对应的块移动计划后,会由一个线程池来处理此请求。但是处理逻辑主要分为以下几步:

1. 解析块移动计划中的源与目的磁盘生成一个对应的VolumePair,并会设置限流、容忍的最大错误数、移动数据大小等
2. 获取当前磁盘中某一个blockPool的块迭代器,选取一个Block
3. 在目的磁盘容量允许的情况下进行块复制。块先复制到目的磁盘的tmp目录,然后挪到finalized目录。
4. 复制完成后首先进行块汇报,让NameNode更新磁盘块存储信息。然后删除源磁盘包含的源块。
   注:在datanode进行块复制时不加锁,只有在更新块状态、更新volumeMap时会加锁;只会移动finalized状态下的块,即完成写入的块。
5. 复制完成后,计算拷贝速率,如果拷贝速率超过设置阈值会进行sleep。
6. 检测拷贝数据大小是否超过plan预期设置,如果没有会继续执行2-5。否则当前Plan执行完毕。

使用

1. 首先要确保DataNode的配置dfs.disk.balancer.enabled为true.

2. 通过-plan生成plan: 

   例如:hdfs diskbalancer -plan datanode1  -maxerror 5  -bandwidth 5 -thresholdPercentageb 20

   plan阶段生成的plan文件会输出在日志中。例如

{"volumeSetPlans":[{"@class":"org.apache.hadoop.hdfs.server.diskbalancer.planner.MoveStep",
  "sourceVolume":                  {"path":"/data/block/","capacity":3891482583040,"storageType":"DISK","used":490711027095,"reserved":0,"uuid":"DS-6d419ead-c216-4550-ba61-1a7e4971013d","failed":false,"volumeDataDensity":-9.999999999998899E-5,"skip":false,"transient":false,"readOnly":false},
 "destinationVolume":{"path":"/data01/block/","capacity":3946313150464,"storageType":"DISK","used":496840825643,"reserved":0,"uuid":"DS-f7d0f75a-0bff-47dc-b5d9-26da37681647","failed":false,"volumeDataDensity":1.0000000000001674E-4,"skip":false,"transient":false,"readOnly":false},"idealStorage":0.1259,
  "bytesToMove":494676490171,"volumeSetID":"1607b421-ffaf-428c-9a0d-7740bbb8a2d5","maxDiskErrors":5,"bandwidth":5}],
  "nodeName":"***","nodeUUID":"2c5c995d-48ae-4cd4-a140-ae5e05732908","port":9867,"timeStamp":1626244761159}

3. 通过-execute执行plan阶段生成的plan文件:

例如:hdfs diskbalancer -execute /system/diskbalancer/datanode1.plan.json

其它使用:

- 查询指定DataNode磁盘balance的状况
  -  命令:hdfs diskbalancer -query datanode1
  -  实现: 此命令就是调用clientDataNodeProtocol.queryDiskBalancerPlan()方法获取对应DataNode的磁盘均衡的状态。
- 取消指定DataNode的磁盘均衡
  - 命令:hdfs diskbalancer -cancel -node datanode1
  - 实现:此命令就是调用clientDataNodeProtocol.cancelDiskBalancePlan()方法取消对应DataNode的磁盘均衡的状态。

相关参数介绍:

-paln:给指定的DataNodes生成Plan。

-thresholdPercentage:生成Plan时,允许申明移动成功的移动数据与计划移动数据的百分比,当成功移动数据比上计划移动数据的百分比小于等于此数据的时候可以表明平衡。

-bandwidth:生成Plan时拷贝数据的限流参数,默认0

-maxerror:生成Plan时,拷贝过程中容忍的最大异常次数,默认0

-execute: 对指定文件内的Datanode进行磁盘balance。

-query:查询指定DataNode磁盘balance的状况

-cancel:取消指定文件包含DataNode的磁盘均衡

-report:列出磁盘均衡效果比较好的DataNode

-out:指定输出文件

-plan与-excute不能同时指定

参考:

[doc] , HDFS Disk Balancer , 2017-12-08