12.1.1 内存分配控制

1. vm.overcommit_memory

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

image.png

申请内存后, 并不会马上使用内存, 这种技术叫做 overcommit。如果 Redis 在启动时有上面的日志, 说明 vm.overcommit_memory=0, Redis 提示把它设置为1。

image.png

  • 本节的可用内存代表物理内存与 swap 之和
  • 日志中的 Background save 代表的是 bgsave 和 bgrewriteaof, 如果当前可用内存不足, 操作系统应该如何处理fork操作
    • 如果 vm.overcommit_memory=0, 代表如果没有可用内存, 就申请内存失败, 对应到 Redis 就是执行 fork 失败, 在 Redis 的日志会出现:
  1. Cannot allocate memory
  • Redis 建议把这个值设置为1, 是为了让 fork 操作能够在低内存下也执行成功

2. 获取和设置

  1. # 获取
  2. # cat /proc/sys/vm/overcommit_memory
  3. 0
  4. # 设置
  5. echo "vm.overcommit_memory=1" >> /etc/sysctl.conf
  6. sysctl vm.overcommit_memory=1

3. 最佳实践

  • Redis 设置合理的 maxmemory, 保证机器有20%~30%的闲置内存
  • 集中化管理 AOF 重写和 RDB 的 bgsave
  • 设置 vm.overcommit_memory=1, 防止极端情况下会造成 fork 失败

12.1.2 swappiness

1. 参数说明

在 Linux 中, 并不是要等到所有物理内存都使用完才会使用到 swap, 系统参数 swppiness 会决定操作系统使用 swap 的倾向程度。

  • swappiness 的取值范围是0~100
  • swappiness 的值越大, 说明操作系统可能使用 swap 的概率越高, swappiness 值越低, 表示操作系统更加倾向于使用物理内存
  • swappiness 默认值是60

image.png

2. 设置方法

  1. # 重启后失效
  2. echo {bestvalue} > /proc/sys/vm/swappiness
  3. # 永久有效
  4. echo vm.swappiness={bestvalue} >> /etc/sysctl.conf

3. 如何监控 swap

(1) 查看 swap 的总体情况

free 命令:

  1. free -m

(2) 实时查看 swap 的使用

vmstat 命令:

  • 关注 si (swap in) 和 so (swap out)
  1. vmstat 1

(3) 查看指定进程的 swap 使用情况

Linux 操作系统中, /proc/{pid} 目录是存储指定进程的相关信息, 其中 /proc/{pid}/smaps 记录了当前进程所对应的内存映像信息.

通过 info server 获取 Redis 的进程号 process_id:

  1. redis-cli -h ip -p port info server | grep process_id
  2. process_id:986

通过 cat /proc/986/smaps 查询 Redis 的 smaps 信息, 由于有多个内存块信息, 这里只输出一个内存块镜像信息进行观察:

image.png

  • swap 代表该内存块存在 swap 分区的数据大小

总的 swap 用量:

image.png

12.1.3 THP

Redis 日志中建议将此特性进行禁用, 禁用方法如下:

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

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

12.1.4 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 杀掉, 设置方法如下:

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

12.1.5 使用 NTP

Network Time Protocol, 网络时间协议

假如多个 Redis 实例所在的服务器时钟不一致, 对于一些异常情况的日志排查是非常困难的.

image.png

12.1.6 ulimit

假设当前 open files 是4096, 那么启动 Redis 时会看到如下日志:

image.png

日志解释如下:

  • 第一行: Redis 建议把 open files 至少设置成 10032, 那么这个10032是如何来的呢? 因为 maxclients 默认是10000, 这些是用来处理客户端连接的, 除此之外, Redis 内部会使用最多32个文件描述符, 所以这里的10032=10000+32
  • Redis 不能将 open files 设置成10032, 因为它没有权限设置
  • 当前系统的 open files 是4096, 所以将 maxclients 设置成4096-32=4064个, 如果你想设置更高的 maxclients, 请使用 ulimit -n 来设置

Open files 的设置方法如下:

  1. ulimit Sn {max-open-files}

12.1.7 TCP backlog

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

  1. # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/
  2. net/core/somaxconn is set to the lower value of 128.
  1. # 查看
  2. # cat /proc/sys/net/core/somaxconn
  3. 128
  4. # 修改
  5. echo 511 > /proc/sys/net/core/somaxconn