Redis详解(5)常见问题和解决方法

Redis详解(5)常见问题和解决方法
最新回答
茴菿原点

2022-11-19 09:21:47

Redis 常见问题及解决方法详解

一、Redis Master 性能调优问题

问题表现
  • Master 执行内存快照时调用 save 命令触发 rdbSave 函数,阻塞主线程导致服务性能大幅下降。
  • Master 使用 AOF 持久化时,若不重写 AOF 文件对性能影响较小,但 AOF 文件持续增大会影响 Master 重启恢复速度。
  • Master 执行 BGREWRITEAOF 重写 AOF 文件时,消耗大量 CPU 和内存资源,导致服务负载过高、短暂服务中断。
原因分析
  • 定时任务遗留:原 Master 机器作为 Slave 时设有每日上午 10 点执行 BGREWRITEAOF 的 shell 定时任务,切换为 Master 后未删除该任务。
  • 系统 I/O 瓶颈:硬盘读写速度不足导致主进程的 fsync()/write() 操作被阻塞。
解决方法
  • 临时缓解方案:将 no-appendfsync-on-rewrite 配置设为 yes,在重写期间不执行 fsync 操作,新的写入操作暂时存储在内存中,等重写完成后再写入。
  • 最佳方案:不在 Master 上启用 AOF 备份功能。
优化建议
  • 持久化策略

    Master 最好不进行任何持久化操作,包括内存快照和 AOF 日志文件,尤其是不要使用内存快照进行持久化。

    如果数据关键,某个 Slave 应启用 AOF 备份数据,策略为每秒同步一次。

  • 主从部署

    为了主从复制的速度和连接的稳定性,Slave 和 Master 最好位于同一局域网内。

    尽量避免在负载较高的 Master 上添加 Slave。

    为了 Master 的稳定性,主从复制应使用单向链表结构而非图状结构,即主从关系应为:Master -> Slave1 -> Slave2 -> ...

二、Redis 连接错误:MISCONF

问题表现

连接 Redis 数据库时报错:MISCONF Redis is configured to save RDB snapshots, but it is currently not able to persist on disk. Commands that may modify the data set are disabled, because this instance is configured to report errors during writes if RDB snapshotting fails (stop-writes-on-bgsave-error option).

原因分析

强制关闭了 Redis 快照,导致无法持久化到硬盘。

解决方法

将 stop-writes-on-bgsave-error 值设置为 no,有两种修改方法:

  • 命令行修改
127.0.0.1:6379> config set stop-writes-on-bgsave-error no
  • 修改配置文件

    使用 vi 打开 redis-server 配置的 redis.conf 文件。

    使用快捷匹配模式:/stop-writes-on-bgsave-error 定位到 stop-writes-on-bgsave-error 字符串所在位置。

    将后面的 yes 改为 no。

三、Redis AOF 文件过大问题

问题表现

Redis 集群中某个节点报错:Starting automatic rewriting of AOF on 307% growth Error opening /setting AOF rewrite IPC pipes: Numerical result out of range,表示 AOF 文件超出了存储的最大内容。

原因分析

随着 AOF 文件越来越大,里面会有大部分重复命令或可合并的命令,且 Redis 似乎没有自动触发 BGREWRITEAOF 的稳妥方法。

解决方法
  • 重命名 AOF 文件:将 AOF 文件重命名为【文件.aof.(数字)】,如 appendonly.aof.1,然后创建原文件。
  • 重启节点:如果问题尚未解决,重启出现问题的 Redis 节点。
  • 定时触发重写:建议编写脚本每天定时执行 BGREWRITEAOF 操作。
AOF 重写好处
  • 减少 AOF 日志尺寸,减少内存占用,加快数据库恢复时间。
  • 执行 AOF 文件重写操作会创建一个当前 AOF 文件的体积优化版本。
  • 即使 BGREWRITEAOF 执行失败,也不会有任何数据丢失,因为旧的 AOF 文件在 BGREWRITEAOF 成功之前不会被修改。

四、Redis 突然挂掉后无法启动问题

问题表现

Redis 突然挂掉后无法启动,查看 log 日志发现报错:Short read or OOM loading DB. Unrecoverable error, aborting now。

解决方法rm -f redis/dump.rdbrm -f redis.pid

五、background save db 不成功问题

问题表现

Redis 有时 background save db 不成功,通过 log 发现告警:# WARNING overcommit_memory is set to 0! Background save may fail under low memory condition.

原因分析
  • overcommit_memory 参数:当执行 Redis 的 bgsave 命令时,Redis 会 fork 一个进程将 Redis 中的内存数据写入磁盘。bgsave 时如果有数据变更,同样需要申请内存。当 overcommit_memory 设置为 0 时,内核会检查是否有足够的可用内存供应用进程使用,如果没有足够内存,内存申请失败,可能导致 bgsave 不成功。
  • Overcommit 和 OOM

    Overcommit:Linux 对大部分申请内存的请求都回复 "yes",以便能运行更多更大的程序,因为申请内存后并不会马上使用内存,这种技术称为 Overcommit。

    OOM killer:当 Linux 发现内存不足时,会发生 OOM killer,它会选择杀死一些进程(用户态进程,不是内核线程)以便释放内存。选择进程的函数是 oom_badness 函数,该函数会计算每个进程的点数(0~1000),点数越高,这个进程越有可能被杀死,每个进程的点数跟 oom_score_adj 有关,而且 oom_score_adj 可以被设置(-1000 最低,1000 最高)。

解决方法

将 vm.overcommit_memory 设为 1,有三种方式修改内核参数:

  • 编辑配置文件:编辑 /etc/sysctl.conf,改 vm.overcommit_memory=1,然后 sysctl -p 使配置文件生效。
  • 命令行设置
sysctl vm.overcommit_memory=1
  • 直接写入文件
echo 1 > /proc/sys/vm/overcommit_memory

六、Redis 进程占用 CPU 100%问题

问题表现

通过 top 发现 Redis 进程 CPU 使用率 100%。

原因分析

通过 info 命令检查当前的执行命令情况,发现大量的 keys 命令导致 CPU 使用率过高。

解决方法

检查慢查询 slowlog get,去掉相关服务中的 keys 命令后,服务恢复正常。