zoukankan      html  css  js  c++  java
  • namenode 优化 mv慢的问题

    问题现象

    问题描述

      公司业务程序需求每30分钟mv 一万多个文件,如果三十分钟之内当前的文件内容没有全部移动,程序报错并且停止。

    分析

      通过分析,发现在启动balancer和不启动balancer的情况下,namenode的处理能力差别巨大。不启动balancer,一万多个文件不到20秒全部移动成功,启动balancer的情况下,如果当前需要平衡的数据量大,
    30分钟根本不能全部移动,这时候程序就报错了。如果在启动balancer的情况下,这时候程序正在执行mv操作(已经执行了一段时间,但不到三十分钟),关掉balancer,mv操作基本在两三秒以后就完成。

    优化

    RPC队列拆分(开启SERVER RPC)

    在默认情况下,service RPC端口是没有使用的,client和DataNode汇报,zkfc的健康检查都会公用RPC Server,当client的请求量比较大或者DataNode的汇报量很大,会导致他们之间相互影响,导致访问非常缓慢,开启之后,DN的汇报和健康检查请求都会走Service RPC端口,避免了因为client的大量访问影响,影响服务之间的请求,在HA集群中,可以在hdfs-site.xml中设置。

    <property>
        <name>dfs.namenode.servicerpc-address.mycluster.nn1</name>
        <value>mynamenode1.example.com:8021</value>
      </property>
    
      <property>
        <name>dfs.namenode.servicerpc-address.mycluster.nn2</name>
        <value>mynamenode2.example.com:8021</value>
      </property>

    开启之后,需要重新格式化ZKFC

    hadoop-daemon.sh stop zkfc
    hdfs zkfc –formatZK
    需要重启集群,当然可以分开启动某些节点进程

    注意:该功能对于生产环境,自行评估严重性。最好是两个namenode分开启动,防止namenode不可用。

    HDFS审计日志

    1、开启审计日志

    HDFS审计日志是一个和进程分离的日志文件,默认是没有开启的,开启之后,用户的每个请求都会记录到审计日志当中,通过审计日志可以发现哪些ip,哪些用户对哪些目录做了哪些操作,比如:那些数据在哪些在什么时候删除,和分析哪些Job在密集的对NameNode进行访问。

    修改hadoop-env.sh文件

    -Dhdfs.audit.logger=${HDFS_AUDIT_LOGGER:-INFO,NullAppender}

    修改为

    -Dhdfs.audit.logger=${HDFS_AUDIT_LOGGER:-INFO,RFAAUDIT}

    对应的log4j.properties可以新增保存个数以及配置日志文件的位置

    #
    # hdfs audit logging
    #
    hdfs.audit.logger=INFO,NullAppender
    hdfs.audit.log.maxfilesize=2560MB           //默认是256m
    hdfs.audit.log.maxbackupindex=30        //默认是20
    log4j.logger.org.apache.hadoop.hdfs.server.namenode.FSNamesystem.audit=${hdfs.audit.logger}
    log4j.additivity.org.apache.hadoop.hdfs.server.namenode.FSNamesystem.audit=false
    log4j.appender.RFAAUDIT=org.apache.log4j.RollingFileAppender
    log4j.appender.RFAAUDIT.File=/data1/hadoop/hadoop/logs/hdfs-audit.log       //默认是${hadoop.log.dir}/hdfs-audit.log
    log4j.appender.RFAAUDIT.layout=org.apache.log4j.PatternLayout
    log4j.appender.RFAAUDIT.layout.ConversionPattern=[%d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX}] [%p] %c{3}.%M(%F %L) [%t] : %m%n
    log4j.appender.RFAAUDIT.MaxFileSize=${hdfs.audit.log.maxfilesize}
    log4j.appender.RFAAUDIT.MaxBackupIndex=${hdfs.audit.log.maxbackupindex}

    2、开启异步审计日志

    使用异步的log4j appender可以提升NameNode的性能,尤其是请求量在10000 requests/second,可以设置hdfs-site.xml

    <property>
        <name>dfs.namenode.audit.log.async</name>
        <value>true</value>
      </property>

    <property>

        <name>dfs.namenode.edits.asynclogging</name>

        <value>true</value>

      </property>

    3、关闭多余的日志

    有时候,NameNode上日志打印会严重影响NN的性能,出问题时也会造成没必要的干扰,所以可以修改log4j的文件,对没必要的日志进行日志级别的调整,例如

    log4j.logger.BlockStateChange=WARN
    log4j.logger.org.apache.hadoop.ipc.Server=WARN

    RPC FairCallQueue(公平调度策略)

    这个是基于上面第一点开启Service RPC继续说的,这是较新版本的Hadoop的新特性,RPC FairCallQueue替换了之前的单一的RPC queue的模式,RPC Server会维护并按照请求的用户进行分组,Handler会按照队列的优先级去消费queue里面的RPC Call,这个功能它可以防止因为某个用户的cleint的大量请求导致NN无法响应,整个集群瘫痪的状态,开启了之后,请求多的用户请求会被降级,这样不会造成多租户下,影响他用户的访问。

    如需开启,修改core.-site.xml

    <property>
        <name>ipc.8020.callqueue.impl</name>
        <value>org.apache.hadoop.ipc.FairCallQueue</value>
      </property>
    <property>
      <name>ipc.8020.faircallqueue.decay-scheduler.period-ms</name>
      <value>60000</value>
    </property>
    <property>
      <name>ipc.8020.backoff.enable</name>     //开启rpc 客户端 拥塞控制
      <value>true</value>
    </property>
    ipc.8020.scheduler.priority.levels //队列优先级,默认是4,基于提交用户来区分,目前就hadoop一个用户,所以不需要调整该参数,客户端用户数越多的情况,效果越明显
    ipc.8020.scheduler.impl //默认DefaultRpcScheduler,这里只是记录一下,该参数配置以后,启动namenode提示找不到改类,这里仅仅记录一下。

    注意:不能对Datanode 和NameNode的端口开启。

    避免读取stale DataNodes(也就是坏数据)

    修改hdfs-site.xml

    dfs.namenode.avoid.read.stale.datanode=true
    dfs.namenode.avoid.write.stale.datanode=true

    开启short circuit reads(短路读取)

    开启短路读之后,当client读取数据时,如果在改节点,会直接通过文件描述符去读取文件,而不用通过tcp socket的方式(也就是绕过了datanode,不从datanode去读取数据)

    修改hdfs-site.xml

    dfs.client.read.shortcircuit=true
    dfs.domain.socket.path=/var/lib/hadoop-hdfs/dn_socket   //该路径是存放数据块的目录

    设置系统CPU为performance

    设置cpu的scaling governors为performance模式,你可以运行cpufreq-set -r -g performance或者修改/sys/devices/system/cpu/cpu*/cpufreq/scaling_governor文件,并设置为performance

    关闭操作系统的Transparent Huge Pages (THP)

    #cat /sys/kernel/mm/transparent_hugepage/defrag    //查看透明缓存页
    [always] madvise never                  //默认是开启的

    # echo "never" >
    /sys/kernel/mm/transparent_hugepage/defrag //关闭透明缓存页,注意,该方式重启以后失效,如果需要永久有效,可以把命令添加到/etc/rc.local文件里面
    
    

    设置系统能使用交换分区的值

    在大多数系统中,该值默认为60,该值越高,说明把内存数据交换到交换分区越积极,这对大数据集群来说,会影响稳定性和可用性。范围0-100

    #sysctl -w vm.swappiness = 10    //不要设置为0

    配置balancer 获取信息节点

    将hdfs balancer获取存储信息的请求发送到standby namenode以及忽略小的数据块

    修改hdfs-site.xml文件

    <property>
    
        <name>dfs.namenode.balancer.request.standby</name>     //这个值在hadoop2.9.2版本与hadoop3.2版本的默认配置文件中未找到,设置以后,发现集群的balancer依然获取的是active节点,这里仅仅记录一下
    
        <value>true</value>
    
      </property>
    
      <property>
    
        <name>dfs.balancer.getBlocks.min-block-size</name>
    
        <value>10485760</value>
    
      </property>

    调整namenode handler

    修改hdfs-site.xml文件

    <property>
         <name>dfs.namenode.handler.count</name>    //如果没有配置service rpc  ,那么该参数配置的值处理所有的call
         <value>70</value>                //该参数的建议值:集群的自然对数 * 20 例如:python -c "import math;print(math.log(70) *20)",70为集群大小
    </property>

    <property>
      <name>dfs.namenode.service.handler.count</name>    //在开启service rpc的情况配置改参数,用于处理datanode 上报数据块和心跳的线程数量。
      <value>50</value>
    </property>

    修改jvm GC 的年轻代

    当前系统heap大小为15G,整个集群维护了8千万左右的文件、目录和块的信息,集群使用堆内存已经达到了10G左右,在查看集群的时候,发现一分钟进行好几次的的年轻代GC,二年轻代只有仅仅的几百兆。

    调整策略,年轻代的内存容量最好是整个堆文件的1/3或者1/4

    修改hadoop-env.sh文件,修改 -Xmn为3g

    export HADOOP_NAMENODE_OPTS="-Dhadoop.security.logger=${HADOOP_SECURITY_LOGGER:-INFO,RFAS} -Dhdfs.audit.logger=${HDFS_AUDIT_LOGGER:-INFO,RFAAUDIT} -Xmn3g  -XX:ParallelGCThreads=56  -XX:+UseConcMarkSweepGC -XX:ErrorFile=${HADOOP_HOME}/logs/gc_err.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:${HADOOP_HOME}/logs/gc.log.`date "+%Y-%y-%d"` $HADOOP_NAMENODE_OPTS"

    参考文章:

    cloudera文档

    hortonworks社区

    http://hackershell.cn/?p=1382

    https://www.cnblogs.com/moonypog/p/11008161.html

    http://www.inter12.org/archives/1304

  • 相关阅读:
    织梦开发——相关阅读likeart应用
    织梦标签教程
    织梦专题调用代码
    HIT 2543 Stone IV
    POJ 3680 Intervals
    HIT 2739 The Chinese Postman Problem
    POJ 1273 Drainage Ditches
    POJ 2455 Secret Milking Machine
    SPOJ 371 Boxes
    HIT 2715 Matrix3
  • 原文地址:https://www.cnblogs.com/yjt1993/p/11205972.html
Copyright © 2011-2022 走看看