zoukankan      html  css  js  c++  java
  • Redis在linux系统中的优化

      通常来看,Redis开发和运维人员更加关注的是Redis本身的一些配置优化,例如AOF和RDB的配置优化、数据结构的配置优化等,但是对于操作系统是否需要针对Redis做一些配置优化不甚了解或者不太关心。然而事实证明一个良好的系统操作配置能够为Redis服务良好运行保驾护航。

     

    1.内存分配控制

      1.vm.overcommit_memory

      Redis在启动时可能会出现这样的日志:

    # WARNING overcommit_memory is set to 0! Background save may fail under low memory
              condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and
              then reboot or run the command ' sysctl vm.overcornmit_memory=1' for this to take effect.

      在分析这个问题之前,首先要弄清楚什么是overcommit? Linux操作系统对大部分申请内存的请求都回复yes,以便能运行更多的程序。因为申请内存后,并不会马上使用内存,这种技术叫做overcommit。如果Redis在启动时有上面的日志,说明vm.overcommit_memory=0,Redis 提示把它设置为 1。

      vm.overcommit_memory用来设置内存分配策略,有三个可选值,如表12-1所示。

    表 12-1 vm.overcommit_memory 的三个可选值及说明
    含 义
    0

    表示内核将检査是否有足够的可用内存。如果有足够的可用内存,

    内存申请通过,否则内存申请失败,并把错误返回给应用进程

    1 表示内核允许超量使用内存直到用完为止
    2

    表示内核决不过量的("never overcommit") 使用内存,

    即系统整个内存地址空间不能超过swap+50%的RAM值,50%是overcommit ratio 默认值,此参数同样支持修改

      日志中的Background save代表的是bgsave和bgrewriteaof,如果当前可用内存不足,操作系统应该如何处理fork 操作。如果vm.overcommit_memory=0,代表如果没有可用内存,就申请内存失败,对应到Redis就是执行fork 失败,在Redis的日志会出现:

    Cannot allocate memory

      Redis建议把这个值设置为1,是为了让fork操作能够在低内存下也执行成功。

     

      2.获取合适置

      获取:

    # cat /proc/sys/vm/overcommit_memory
    0

      设置:

    echo "vm.overcommit_memory=1" >> /etc/sysctl.conf
    sysctl vm.overcommit_memory=1

      3.最佳实践

    □ Redis设置合理的maxmemory,保证机器有20% ~ 30%的闲置内存。

    □ 集中化管理AOF 重写和RDB的bgsave。

    □ 设置vm.overcommit_memory=1, 防止极端情况下会造成fork失败。

     

    2.swappiness

      1.参数说明

      swap对于操作系统来比较重要,当物理内存不足时,可以将一部分内存页进行swap操作,已解燃眉之急。但世界上没有免费午餐,swap空间由硬盘提供,对于需要高并发、高吞吐的应用来说,磁盘IO通常会成为系统瓶颈。在 Linux中,并不是要等到所有物理内存都使用完才会使用到swap,系统参数swppiness会决定操作系统使用swap的倾向程度。swappiness的取值范围是0 ~ 100, swappiness的值越大,说明操作系统可能使用swap的概率越高,swappiness值越低,表示操作系统更加倾向于使用物理内存。swap的默认值是60, 了解这个值的含义后,有利于Redis的性能优化。表12-2对 swappiness的重要值进行了说明。

    表 12-2 swapniess 重要值策略说明
    策略
    0

    Linux3.5 以及以上: 宁愿用OOM killer 也不用swap

    Linux3.4 以及更早: 宁愿用 swap也不用OOM killer

    1 Linux3.5 以及以上:宁愿用swap也不用OOM killer
    60 默认值
    100 操作系统会主动地使用 swap

      从表12-2中可以看出,swappiness参数在Linux3.5版本前后的表现并不完全相同,Redis运维人员在设置这个值需要关注当前操作系统的内核版本。

     

      2.设置方法

      swappiness设置方法如下:

    echo {bestvalue} > /proc/sys/vm/swappiness

      但是上述方法在系统重启后就会失效,为了让配置在重启Linux操作系统后立即生效,只需要在 /etc/sysctl.conf 追加 vm.swappiness={bestvalue} 即可。

    echo vm.swappiness={bestvalue} >> /etc/sysctl.conf

      需要注意 /proc/sys/vm/swappiness是设置操作,/etc/sysctl.conf是追加操作。

     

    3.THP

      Redis在启动时可能会看到如下日志:

    WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This
              will create latency and memory usage issues with Redis. To fix this issue run
              the command ' echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root,
              and add it to your / etc/rc.local in order to retain the setting after a reboot.
              Redis must be restarted after THP is disabled.

      从提示看Redis建议修改Transparent Huge Pages (THP) 的相关配置,Linux kernel在2.6.38内核增加了THP特性,支持大内存页(2MB) 分配,默认开启。当开启时可以降低fork 子进程的速度,但 fork 操作之后,每个内存页从原来4KB变为2MB, 会大幅增加重写期间父进程内存消耗。同时每次写命令引起的复制内存页单位放大了512倍,会拖慢写操作的执行时间,导致大量写操作慢查询,例如简单的 incr 命令也会出现在慢查询中。因此Redis日志中建议将此特性进行禁用,禁用方法如下:

    echo never > /sys/kernel/mm/transparent_hugepage/enabled

      为了使机器重启后THP配置依然生效,可以在/etc/rc.local中追加 echo never >/sys/kernel/mm/transparent_hugepage/enabled 。

      在设置THP配置时需要注意:有些Linux的发行版本没有将THP放到 /sys/kernel/mm/transparent_hugepage/enabled中,例如 Red Hat 6 以上的 THP 配置放到/sys/kernel/mm/redhat—transparent_hugepage/enabled中。而Redis 源码中检查 THP时,把 THP位置写死:

    FILE *fp = fopen ("/sys/kernel/mm/transparent_hugepage/enabled"," r " ) ;
    if (!fp) return 0;

      所以在发行版中,虽然没有THP的日志提示,但是依然存在THP所带来的问题:

    echo never  > /sys/kernel/mm/redhat_transparent_hugepage/enabled

    4.OOM killer

      OOM killer会在可用内存不足时选择性地杀掉用户进程,它的运行规则是怎样的,会选择哪些用户进程“下手”呢? OOM killer 进程会为每个用户进程设置一个权值,这个权值越高,被“下手”的概率就越高,反之概率越低。每个进程的权值存放在/proc/{progress—id }/oom_score 中,这个值是受/proc/{progress_id}/oom_adj 的控制,oom_adj在不同的 Linux 版本中最小值不同,可以参考 Linux 源码中oom.h (从-15到-17)。当oom_adj设置为最小值时,该进程将不会被OOM killer杀掉,设置方法如下。

    echo {value} > /proc/${process_id}/oom_adj

      对于Redis所在的服务器来说,可以将所有Redis的oom_adj设置为最低值或者稍小的值,降低被ooM killer 杀掉的概率:

    for redis_pid in $ (pgrep -f " redis-server" )
    do
            echo -17 > /proc/${ redis_pid}/oom_adj
    done

    5.ulimit

      如果设置比较低,就会出现一下提示。这里不多做解释。

    # You requested maxclients of 10000 requiring at least 10032 max file descriptors .
    # Redis can't set maximum open files to 10032 because of OS error: Operation not permitted.
    # Current maximum open files is 4096. Maxclients has been reduced to 4064 to compensate
           for low ulimit. If you need higher maxclients increase 'ulimit  - n'  .

      日志解释如下:

    □ 第一行:Redis建议把open files至少设置成10032,那么这个10032是如何来的呢?因为maxclients默认是10000,这些是用来处理客户端连接的,除此之外,Redis内部会使用最多32个文件描述符,所以这里的10032 = 10000 + 32。

    □ 第二行:Redis不能将open files设置成10032,因为它没有权限设置。

    □ 第三行:当前系统的open files是 4096,所以将max clients设置成4096-32=4064个,如果你想设置更高的maxclien ts, 请使用ulimit -n 来设置。从上面的三行日志分析可以看出open files的限制优先级比maxclients大。

     

    6.TCP backlog

      Redis默认的tcp-backlog值为511,可以通过修改配置tcp-backlog进行调整,如果 Linux的tcp-backlog小于Redis设置的tcp-backlog,那么在Redis启动时会看到如下日志:

    # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/
                 net/core/somaxconn' is set to the lower value of 128

      查看方法:

    # cat /proc/sys/net/core/somaxconn
    128

      修改方法:

    echo 511 > /proc/sys/net/core/somaxconn

    7.总结

      Linux相关优化:

    • vm.overcommit_memory 建议为 1。
    • Linux>3.5, vm.swappiness 建议为 1 , 否则建议为 0。
    • Transparent Huge Pages(THP)建议关闭掉,但需要注意 Linux 发行版本改变了THP的配置位置。
    • 可以为Redis进程设置oom_adj,减少Redis被 ppM killer杀掉的概率,但不要过度依赖此特性。
    • 建议对Redis所有节点所在机器使用NTP服务。
    • 设置合理的ulimit保证网络连接正常。
    • 设置合理的tcp-backlog参数。

    作者:小家电维修

    相见有时,后会无期。

  • 相关阅读:
    Mysql 主备原理
    Mysql-innodb日志写入时机
    Innodb 架构
    Reactor/Proactor
    select,poll,epoll,IO多路复用进化史
    从硬件+操作系统的角度解释为什么操作系统的IO单位是磁盘块
    Dubbo 核心功能在业务架构中的体现
    Mysql-Innodb 锁总结
    第一阶段冲刺三
    第一阶段冲刺二
  • 原文地址:https://www.cnblogs.com/lizexiong/p/14730730.html
Copyright © 2011-2022 走看看