Hadoop 各节点负载均衡
背景:
对于HDFS集群,经常长时间的运行,数据量会增趋势性增长,hdfs的使用率会越来越饱和,此时会对hdfs进行扩容,而扩容之后为了提高各个datanode之间的分布式读写效率,必须实现节点之间的负载均衡。另外集群经过大量的delete操作后,各个Datanode上的空间使用率可能会存在比较大的差异,少数使用率过高的Datanode会导致对其的数据访问效率变低,并且如果该Datanode挂掉,需要更多的时间进行恢复,对集群也会造成更大的影响,基于此,本文基于hadoop自带的balancer机制进行研究。
负载均衡命令:
bin/start-balancer.sh[-threshold <threshold>]
原理解析:
通过上面的命令可以使Hadoop对各个Datanode进行评估并使他们保持平衡,参数threshold表示的平衡的阀值,取值范围在0%到100%之间,该参数表示每个Datanode中空间使用率与HDFS集群总的空间使用率的差距百分比,阀值设置的越小,那么HDFS各个Datanode的使用率越接近,整个集群也更加的平衡,但会需要消耗更多的时间和资源来达到该平衡状态,如果阀值设置的过小,那么对于操作非常频繁的HDFS集群,有可能永远也不会达到该阀值所指定的平衡状态,阀值设置的越大,那么HDFS各个Datanode的使用率差距越大,但是会较容易达到。
通过对源码的解析发现:整个balancer过程还是比较复杂的,首先会计算集群总的使用率,然后分别计算各个活着的Datanode结点的使用率,根据balancer阀值对各个Datanode进行分类,找到那些使用率过高的和使用率过低的结点。遍历使用率过高的结点,找到适合迁移BLOCK的目标结点,原则就是最好是同一机架,如果当前机架没有适合的才会考虑其他机架,把BLOCK从使用率高的结点拷贝到使用率低的结点,在每次递归的过程中,单个Datanode转移或者接受的BLOCK不过超过10G或者它存储能力的阀值(根据该Datanode的总空间决定),并且每次递归过程也不能执行超过20分钟,在每次递归过后,会更新Datanode的最新状态信息,重新计算使用率,决定下一次递归的执行,整个递归过程,最多会执行5次。
通过参数dfs.balance.bandwidthPerSec可以现在balancer过程所占用的网络带宽,单位为每秒字节数,默认值为1M/S。如果你的集群比较空闲或者带宽比较大,可以适当的增加该参数,来加速整个balancer过程,如果你的集群比较繁忙或者带宽比较小,就要调小该参数,但这个balancer过程会变得缓慢,对该参数的参数,只有在HDFS下次启动后才可以生效。
单节点内部分区平衡性:
datanode内部通常会存在多个分区用于提供并行的读写请求,那么hadoop的balancer机制能实现分区层面的数据负载吗?答案是否定的。
hadoop balancer目前为止不会自动平衡node内部的数据,也就是说,如果遇到我们上述的情况,hadoop根本不会管理,而是只是考虑数据的总量。
假设某datanode节点上有两个分区:
/data1100% total 100GB
/data2 10% total 100GB
hadoop存储数据时还是将数据尝试平分到两个分区,但是由于第一个分区已经用完,此时hadoop则会放弃在这个node存储更多的数据。这个结果是我们不愿意看到的。查阅官方wiki文档后发现如下答案:
Hadoop currentlydoes not have a method by which to do this automatically. To do this manually:
1.Take down theHDFS
2.Use the UNIXmv command to move the individual blocks and meta pairs from one directory toanother on each host
3.Restart theHDFS
即:先停掉hdfs集群,然后使用类似mv的命令将数据块和相关的meta文件同时复制到另一个分区即可。