hadoop2.2.0 balance机制总结

来源:互联网 发布:php微信开发教程 编辑:程序博客网 时间:2024/06/06 04:11

最近在搞balance优化,借此机会,打算整理总结一下balance的机制。


1、先看balance 的命令:

     $HADOOP_HOME/sbin/start-balancer.sh -h

   

 Usage: java Balancer        [-policy <policy>]      the balancing policy: datanode or blockpool        [-threshold <threshold>]        Percentage of disk capacity

含义比较明显,默认使用的datanode policy,用的时候一般设置一下 threshold 就行,这个参数是触发进行balance的阈值,默认是10,意思是集群中datanode空间使用率差了10%就开始balance

2、如何限制balance时所占用的带宽

      打开balance的时候,需要加上一个额外的命令,限制balance操作挪动数据块所占的带宽:

      

              $HADOOP_HOME/bin/hdfs dfsadmin -setBalancerBandwidth  5388608  

上面命令表示设置balance带宽5M,可以根据集群繁忙程度动态调制


3、balance 流程

       先获取namenode连接,主要的操作都需要跟namenode交互:

   

final Collection<URI> namenodes = DFSUtil.getNsServiceRpcUris(conf);return Balancer.run(namenodes, parse(args), conf); ……final List<NameNodeConnector> connectors    = new ArrayList<NameNodeConnector>(namenodes.size());try {  for (URI uri : namenodes) {    connectors.add(new NameNodeConnector(uri, conf));  }

这个连接操作比较有用,以后可以通过这个api跟namenode交互

获取namenode连接后,实例化一个Balancer 类,然后开始balance

首先,对datanode的利用率进行统计分级,分为:

aboveAvgUtilizedDatanodes

private boolean isAboveAvgUtilized(BalancerDatanode datanode) {    final double avg = policy.getAvgUtilization();    return (datanode.utilization <= (avg+threshold))        && (datanode.utilization > avg);  }

overUtilizedDatanodes

private boolean isOverUtilized(BalancerDatanode datanode) {    return datanode.utilization > (policy.getAvgUtilization()+threshold);  }

belowAvgUtilizedDatanodes

private boolean isBelowOrEqualAvgUtilized(BalancerDatanode datanode) {    final double avg = policy.getAvgUtilization();    return (datanode.utilization >= (avg-threshold))             && (datanode.utilization <= avg);  }

underUtilizedDatanodes

 private boolean isBelowOrEqualAvgUtilized(BalancerDatanode datanode) {    final double avg = policy.getAvgUtilization();    return (datanode.utilization >= (avg-threshold))             && (datanode.utilization <= avg);  }

这里可以保留第一种情况,这样针对两种利用率极端的datanode进行balance操作,尽快减轻利用率最大的datanode的压力

下面就是针对选取的 <src , des> datanode 进行拷贝数据块的操作了:

启动一个线程池执行挪动数据操作,默认线程数1000

用语言描述一下大致过程:

  chooseNextBlockToMove (选取待挪动数据块),if (取出来null),调用 getBlockList() 获取源datanode的数据块;

如果选出正常数据块,调用dispatch() 方法启动数据块挪动,操作的核心代码:

private void dispatch() {      Socket sock = new Socket();      DataOutputStream out = null;      DataInputStream in = null;      try {        sock.connect(            NetUtils.createSocketAddr(target.datanode.getXferAddr()),            HdfsServerConstants.READ_TIMEOUT);        sock.setKeepAlive(true);                OutputStream unbufOut = sock.getOutputStream();        InputStream unbufIn = sock.getInputStream();        if (nnc.getDataEncryptionKey() != null) {          IOStreamPair encryptedStreams =              DataTransferEncryptor.getEncryptedStreams(                  unbufOut, unbufIn, nnc.getDataEncryptionKey());          unbufOut = encryptedStreams.out;          unbufIn = encryptedStreams.in;        }        out = new DataOutputStream(new BufferedOutputStream(unbufOut,            HdfsConstants.IO_FILE_BUFFER_SIZE));        in = new DataInputStream(new BufferedInputStream(unbufIn,            HdfsConstants.IO_FILE_BUFFER_SIZE));                sendRequest(out);        receiveResponse(in);        bytesMoved.inc(block.getNumBytes());        LOG.info( "Moving block " + block.getBlock().getBlockId() +              " from "+ source.getDisplayName() + " to " +              target.getDisplayName() + " through " +              proxySource.getDisplayName() +              " is succeeded." );}



一直循环,指到挪动的数据块的大小达到了要挪动的数据量,退出






原创粉丝点击