- 说明:以下用source node代表move 的源节点(磁盘占用率较高的节点), target node代表move 的目标节点(磁盘占用率较低的节点)。
balancer的作用是把数据从磁盘占用率高的节点move到磁盘占用率低的节点,解决集群磁盘占用不均匀的问题。
实现的过程就是不断地迭代检查hdfs集群各个节点的磁盘占用情况并进行移动,直到因为集群相对平衡或者没有block可以移动等原因才停止。
这里简单介绍一下相关的代码分析。
1 . balancer每次迭代开始后,通过init()方法从namenode获取各个datanode的磁盘占用情况。主要完成了下列功能:
1.1 将节点封装为 StorageGroup ,分类放入4个集合。节点封时设置了maxSize2Move 值,这个就是每次迭代时,从datanode能搬数据的最大值。默认10G,由参数 dfs.balancer.max-size-to-move 配置。
overUtilizedDatanodes:过载的datanode信息, > 平均使用率+ threshold
aboveAvgUtilizedDatanodes:大于阈值的datanode信息, > 平均使用率 && < 平均使用率+ threshold
belowAvgUtilizedDatanodes:小于阈值的datanode信息, <平均使用率 && > 平均使用率- threshold
underUtilizedDatanodes:负载的datanode信息, < 平均使用率 - threshold
1.2 将封装 StorageGroup,放入总的storageGroupMap(这个后续用于更新block的location时用到)
1.3 这步执行完成后计算并提示,需要移动多少数据量后集群达到平衡。
- 然后通过chooseStorageGroup()匹配move的source和target节点建立拓扑,即决定了从哪往哪搬。把datanode分成source node和 target node两个集合。
2.1 将上面4个集合,overUtilized -> underUtilized, overUtilized->belowAvgUtilized, underUtilized->aboveAvgUtilized 匹配建立 source->target的拓扑
2.2 匹配时先按,同机架配置,再匹配其他的。
2.3 返回本次迭代,实际需要搬的数据量
- 然后进入dispatchBlockMoves()方法进行真正的move操作。
3.1 这时候使用 dispatchExecutor 线程池对第二步得到的source集合,并发对每个srouce执行dispatchBlocks。 这个池的大小就是 dfs.balancer.dispatcherThreads,默认200.
3.2 在这个source节点执行dispatchBlocks时,会通过dispatchBlocks,访问namenode获取,最大2GB的block(MAX_BLOCKS_SIZE_TO_FETCH,注1 )用于move。
3.2.1 然后对将每个block封装成PendingMove。
3.2.2 block封装成PendingMove时会选择一个合适block做 move。“合适”需要符合:
a.该block没有被move过
b.该block在target node上没有备份
c.本次移动不会破坏机架感知的条件
d.本次移动不能减少机架上固有的block备份数
3.2.3 然后再选择一个代理源节点,用于副本复制。
3.2.4 同时这个PendingMove 会加入target节点中,target节点中最多能加 dfs.datanode.balance.max.concurrent.moves 个PendingMove 。默认50
这就限制后续对target做move最大并大为50。
3.2.5 用moveExecutor线程池执行 PendingMove.dispatch() 做move。这个池的大小为:dfs.balancer.moverThreads 默认1000。
- 最后就是步断迭代,直到整个集群平衡。
-- 最后结合现状情况做分析优化:
- crontab 重复进程检查脚本。
改进点: 通过源码分析,balancer启动后,会在hdfs每个ns上建立/system/balancer.id文件,用于重复进程监测。所以可以取消原脚本进程监测过程。
验证:如下图,第二红色部分,确实本身已有监测重复进程。
- balancer在联邦模式下是按 每个ns执行的,但上图中未出现ns。
问题:由于之前问题hdfs-site.xml文件,ns没配置ha。修复后正常。
- 现状的搬移效率及优化。(未完待续)
注1:
该参数可以减少rpc请求,增加每次抓取的block量,但再我们cdh5.12.1中是和常量,不能修改,目前已经有patch对此完善。
增加了参数: dfs.balancer.getBlocks.size HDFS-8824