接手 Redis 的人应该都有这种经历:查一个问题,翻配置、翻日志、翻监控,来回折腾半天,最后发现根因就藏在某一行 loglevel 设置或者一个没配好的 maxmemory 里面。所谓 Redis 配置和日志,表面上一个是“事前设定”,一个是“事后记录”,但在实际操作中它们根本拆不开——配置决定行为,日志暴露行为,而故障定位就是在两者之间反复对照的过程。我刚学 Redis 的时候,以为配置就是把 redis.conf 里几个参数改成推荐值,日志嘛,出错看一眼就行。直到有一次排查线上问题,翻了几小时日志才发现问题出在配置文件里一个不起眼的 save 参数上——那一刻我才明白:配置和日志不是两件事,而是同一件事的两面。这篇文章不打算复述官方文档,而是想从“配置怎么定、日志怎么读、两者怎么对得上”这条实操主线出发,把 Redis 配置和日志相关的内容串起来。适合自己搭过 Redis、但总觉得差点意思的开发者,也适合刚接手 Redis 运维、正在跟各种异常日志较劲的运维同学。1. 配置与日志:Redis 运维的一体两面为什么我把“配置”和“日志”放在一起讲?因为处理 Redis 问题的时候,配置和日志从来不是独立的两条线。1.1 配置文件决定了日志里会出现什么配置是预期管理:内存多大、数据怎么持久化、允许谁连接、什么命令算慢。日志是现实反馈:实际占了多少内存、持久化成没成、谁连接失败、哪个命令把主线程卡住了。配置不对,日志里就会反复出现对应的异常;日志看不懂,再好的配置也不知道该往哪里调。举个最简单的例子:maxmemory 配得小,日志里可能看到慢查询增多,因为内存淘汰占用主线程;save 配得太勤,日志里就会出现大量后台保存记录,甚至触发 fork 失败;appendfsync 配成 always,磁盘慢的时候日志里会持续刷“AOF fsync is taking too long”。配置和日志的关系,就像愿望和现实的关系——不对比着看,问题永远是半个问题。所以我的建议是,不管是谁,拿到一台 Redis 实例之后要做两件事:先完整过一遍 redis.conf 的配置清单,再去看启动日志和运行日志。很多人习惯直接跳过配置去看日志,结果日志里提示的“无法保存”“内存不足”,根子全在配置上。1.2 redis.conf 的装载顺序和动态修改能力Redis 的配置来源有三个层次,从高到低分别是:命令行参数、配置文件、默认值。命令行里指定了配置,配置文件里的对应项就不会生效;配置文件里没写,就用编译时内置的默认值。启动 Redis 时如果没显式指定配置文件,Redis 用默认配置启动,那种裸奔状态最容易出问题。启动命令里用 -c 指定配置文件的路径:redis-server /etc/redis/redis.conf。运行时还可以用 CONFIG GET 和 CONFIG SET 动态查看和修改配置,不用重启。这里有个关键点:CONFIG SET 修改的是内存中的值,不会自动写到文件里。想让修改持久化,得再执行一次 CONFIG REWRITE,它会把当前有效的配置回写到 redis.conf 中,同时保留文件里原有的注释。不过要提醒一句,并非所有配置都支持动态修改。端口、日志文件路径这类影响运行时资源分配的配置项,CONFIG SET 往往无法生效。所以在搜“Redis 配置日志”相关内容时,你可能会看到别人用 CONFIG SET 修改慢查询阈值或者内存策略,但从来没人用 CONFIG SET 去改端口,因为根本改不动。配置优先级快速对照:配置来源优先级说明命令行参数最高覆盖配置文件与默认值配置文件 redis.conf次之覆盖默认值编译默认值最低被以上两层覆盖重要提示:线上变更配置,别急着 CONFIG REWRITE。先 CONFIG SET 观察一段时间,确认稳定后再写回文件,否则一旦写回有问题的配置,重启后很难快速回滚。2. 核心配置项解析:内存、持久化与安全Redis 配置项很多,但实际业务里高频被调整、又容易导致日志异常的就那么几类:内存、持久化、网络与安全。我逐个说清楚这些配置该怎么选,以及选错之后日志里会出现什么。2.1 内存上限与淘汰策略:先想清楚 Redis 装得下什么maxmemory 默认在 64 位系统下是 0,表示不限制内存使用,这个状态跑在开发环境没问题,上生产就危险了,内存一旦被数据占满,Redis 进程直接被系统 OOM Kill,日志里基本只会留下操作系统的记录,Redis 自身来不及打任何东西。配置 maxmemory 要结合机器物理内存和业务数据量来算:比如机器内存 16G,系统和其他进程预留 4G,Redis 最多分到 12G,那么 maxmemory 设为 10G 比较稳妥,留 2G 余量给 fork 子进程和内存碎片。别把 maxmemory 当作“刚好存下所有数据”的目标,而是当作“绝对不能超过”的底线。内存满了之后的行为由 maxmemory-policy 控制。这是 Redis 配置里最关键的策略项之一,选择不同策略,直接影响日志中是否会出现命令报错。策略行为适用场景noeviction不做任何淘汰,写命令直接报错需要严格保障数据不丢的场景allkeys-lru从所有 key 中淘汰最近最少使用的纯缓存场景,最常见volatile-lru仅从设置了过期时间的 key 中淘汰缓存+持久化混合场景allkeys-random随机淘汰任意 key访问热度差异不明显时volatile-random随机淘汰带过期时间的 key数据可重建场景volatile-ttl优先淘汰剩余存活时间短的 key对过期时间敏感的缓存我的经验是,业务侧如果接受缓存天然淘汰,优先 allkeys-lru;如果 Redis 里既有缓存数据又有不能丢的数据,noeviction 配合合理的容量规划更安全。还有一种常见组合是 volatile-lru + 所有 key 都设置过期时间,基本等价于 allkeys-lru。内存淘汰还有一点要留意:maxmemory 不设或者设置不合理,日志里不会直接写“内存淘汰了某个 key”,Redis 的淘汰是静默的,只有在慢查询日志里才能间接看到写命令变慢。所以排查内存问题,光看日志是不够的,还要配合 INFO memory 和监控曲线。2.2 持久化配置:RDB 与 AOF 的取舍Redis 持久化有 RDB 快照和 AOF 追加日志两种形式,配置上各有几个关键参数。RDB 靠 save 参数触发,比如默认配置里有这么一段:save 3600 1 save 300 100 save 60 10000意思是 3600 秒内至少有 1 次写操作、300 秒内至少有 100 次写操作、60 秒内至少有 10000 次写操作时,执行一次快照。RDB 文件紧凑、恢复快,但数据丢失窗口大,两次快照之间的写入在宕机时都会丢。AOF 通过 appendonly yes 开启,appendfsync 控制刷盘策略:always 每次写都刷盘,最安全但性能最低;everysec 每秒刷一次,是性能和可靠性的折中;no 交给操作系统决定刷盘时机,数据丢失风险大。线上我一般选 everysec,追求极致安全的场景才用 always。Redis 4.0 之后默认开启混合持久化,也就是 aof-use-rdb-preamble yes,AOF 文件开头用 RDB 格式记录已有数据,后面用 AOF 格式记录增量,兼顾了加载速度和数据完整性。这个配置对日志最直接的影响是重写时的日志关键词,混合模式下日志里的 RDB 和 AOF 相关记录会交替出现。2.3 网络与安全配置:暴露面越小越好bind、protected-mode、requirepass 这三个配置直接决定谁能连上你的 Redis。bind 默认绑定本地回环地址,注释掉之后 Redis 会监听所有网卡,这对局域网环境方便,但一旦服务器有公网 IP,Redis 相当于裸奔在公网上。protected-mode yes 是 Redis 的自我保护机制:如果没有设置 requirepass,且没有显式设置 bind 时,Redis 只接受本机回环连接。这层保护很关键,但也有副作用——很多人配了 bind 指向内网 IP,却忘了 protected-mode 会因此放行,导致公网也能访问。我的建议很简单:生产环境 bind 只写内网网卡 IP 或回环地址,requirepass 必须设置,密码用高强度随机串。日志里如果出现 “Unauthorized connection” 或大量来自陌生 IP 的连接,先去查这三个配置是不是太宽松了。timeout 和 tcp-keepalive 属于连接层面的细节配置。timeout 设置空闲连接多久后被关闭,默认 0 永不过期,容易累积空闲连接。tcp-keepalive 默认 300 秒,建议保留默认值,过短会产生大量探测包,过长会导致失效连接残留。这两个参数配置不当,日志里会看到大量连接被异常断开,表现为客户端突然报超时。3. 日志体系:级别、输出与格式解读配置看得差不多了,说说日志本身。Redis 日志虽然格式简单,但信息量很大,学会看日志级别和格式,很多问题能一眼定位。3.1 日志级别:不是越大声越好loglevel 有四个级别:debug、verbose、notice、warning。默认是 notice,生产环境也是 notice 为主。级别输出内容适合场景debug最详细,包含每个连接、每条命令级别的信息开发环境调试,生产坚决不用verbose较详细,包含连接建立与关闭等本地测试notice常规提示,启动、持久化、同步事件生产默认warning只有关键警告和错误磁盘紧张、日志量受限时我在生产环境见过有人把 loglevel 调成 debug 想排查问题,结果日志一小时写满几个 G,直接把磁盘撑爆,主进程反而因为磁盘满而卡顿。排查问题应该用慢查询日志和监控工具,而不是靠 debug 级别“大海捞针”。3.2 日志输出位置与收集方式logfile 配置指定日志文件路径,常见设置为 /var/log/redis/redis-server.log。如果 logfile 为空字符串,日志会输出到标准输出 stdout,这个设计在容器部署时非常有用,系统会把 stdout 收集到 docker logs 里,日志收集就交给容器平台统一处理。用 systemd 管理 Redis 时,如果 logfile 配置为空,日志会进入 journald,可以直接用 journalctl -u redis-server 查看。这种场景下别再去 /var/log 下面找文件,很多新手在这里卡半天。日志文件需要轮转,不然会无限膨胀。最省事的方式是配置 logrotate,我一般按天轮转、保留 30 份左右。配置参考如下:/var/log/redis/redis-server.log { daily rotate 30 compress delaycompress missingok notifempty copytruncate }注意 copytruncate 这个参数很关键,Redis 持有日志文件的文件句柄,直接 rename 会导致 Redis 继续往旧文件写,只有 copytruncate 能先复制再清空原文件。3.3 读懂 Redis 日志的时间戳与角色标识一条典型的 Redis 日志长这样:12345:M 24 Feb 2025 10:00:00.123 * Ready to accept connections拆开看:12345 是进程 PID,M 是角色标记,后面是时间戳,* 是消息类型,最后是内容。角色标记的含义:M:主节点(Master)S:从节点(Replica/Slave)C:子进程(比如 RDB 或 AOF 后台子进程)X:哨兵(Sentinel)消息类型符号也值得记一下:* 表示普通信息,- 表示警示信息,# 表示错误信息。排查故障时优先看 # 和 - 开头的行,* 多数是启动过程和常规事件。启动日志的序列也很有规律:先是加载配置文件,然后设置 signal handler,接着打开 TCP 端口监听,如果配置了持久化会尝试加载已有数据,最后打出一句 Ready to accept connections。看到这句说明 Redis 基本启动成功,在这之前如果日志中断,问题就在对应的环节。4. 慢查询日志:定位命令级瓶颈的关键很多人以为慢查询日志要额外配置什么插件,其实 Redis 内置了,只是默认阈值设置使大部分环境下不会被触发。慢查询日志记录的是执行时间超过阈值的命令,是排查性能问题时利用率最高的日志。4.1 慢查询的配置与阈值选择两个核心配置:slowlog-log-slower-than 10000 slowlog-max-len 128slowlog-log-slower-than 单位是微秒,默认 10000 微秒也就是 10 毫秒。注意单位是微秒,很多人想配置成 1 毫秒写成 1,结果所有命令都进慢查询日志,数据量瞬间爆炸。想配成 1 毫秒应该写 1000。slowlog-max-len 是内存中最多保存多少条慢查询记录,默认 128。慢查询日志是存内存的,不是写文件,所以这个上限要控制,太小查不到历史,太大又占内存。一般设置 256 到 1024 之间足够。阈值选择上,要根据业务容忍度调整。读多写少的缓存场景,1 毫秒以上的命令已经算慢;批量操作的场景,单条命令几十毫秒可能也正常。我的建议是先从 10 毫秒开始,结合业务监控逐步下调,不要一开始就追求极致。4.2 慢查询的读取与分析命令行下用 SLOWLOG GET 查看最近记录,SLOWLOG LEN 查看记录条数,SLOWLOG RESET 清空记录。返回结果包含四个核心字段:命令执行时间戳、执行耗时(微秒)、命令参数、客户端地址等。实操中我的习惯是先用 SLOWLOG LEN 看数量,再用 SLOWLOG GET 10 取最近 10 条,重点看命令本身和耗时。如果慢查询集中在 KEYS、SMEMBERS 这类 O(N) 复杂度的命令,说明业务侧数据结构使用不合理;如果集中在 SET 这类简单命令,可能是机器负载过高或者持久化刷盘拖累。有一个细节:慢查询日志里记录的是“命令执行耗时”,不包括网络传输和排队时间。也就是说,客户端觉得 Redis 很慢,但慢查询日志里没记录,问题可能出在网络、客户端连接池或者 Redis 主线程被其他操作阻塞。这时候要去看 CPU 状态和 INFO commandstats,别只盯着慢查询日志。注意:SLOWLOG 输出的命令参数会直接展示键名,如果键名包含敏感业务字段,排查日志时要避免把完整输出分享给无关人员。5. 日志驱动的典型故障排查实录配置和日志的最终价值,都在故障定位上。我挑几个最常遇到的场景,把日志特征和排查思路完整走一遍。5.1 内存膨胀与被动淘汰:日志里的“无声警告”场景:Redis 使用率持续上涨,业务侧反映部分缓存读取落空,数据被刷新。排查时先看 INFO memory,关注 used_memory、used_memory_peak、maxmemory 三个值。实际占用接近 maxmemory 后,Redis 会根据淘汰策略开始清理 key,这个过程默认不打印日志。唯一能感知到的是慢查询日志中逐渐出现 SET/GET 命令耗时增加,因为淘汰本身消耗主线程时间。这类问题的配置根源,往往就是 maxmemory 没设或者设置过大,以及 maxmemory-policy 与业务方预期不一致。我之前处理过一个缓存消失的案例,配置是 noeviction,内存满了之后写命令直接报错,但外部监控只看命中率,忽略了错误率,排查半天才定位到配置上。排查套路:先 CONFIG GET maxmemory 和 maxmemory-policy 确认配置是否符合预期,再看 used_memory 与峰值比例。如果接近上限,按业务 key 大小估算容量,要么扩容,要么优化数据冗余。5.2 fork 失败与持久化中断:日志里的高危信号Redis 做 RDB 快照或 AOF 重写时,需要 fork 一个子进程。fork 失败时会打这样一条日志:67215:M 24 Feb 2025 10:00:05.123 # Can't save in background: fork: Cannot allocate memory这里 Cannot allocate memory 不一定是物理内存不够,多数情况是操作系统的 overcommit 策略不允许进程地址空间一次性映射。解决手段是设置 vm.overcommit_memory 为 1,并检查透明大页是否开启,后者常导致 fork 后内存占用翻倍。我见过最离谱的情况是,Redis 实例本身只占 2G 内存,但系统 vm.overcommit_memory 设为默认的 0,加上连续内存碎片,fork 一直失败,RDB 从未执行成功过。查日志才明白为什么持久化文件一直是好几天前的。另一个高频日志是 AOF fsync 慢:67215:M 24 Feb 2025 10:00:30.456 * Asynchronous AOF fsync is taking too long (disk is busy?). Writing the AOF buffer may slow down Redis.这条说明磁盘 IO 跟不上写入速度,通常发生在机械盘或共享存储上。应对手段包括降低 appendfsync 频率、升级磁盘、错峰执行 AOF 重写。看到这条日志别急着加机器,先看磁盘 IO。5.3 主从同步异常:日志中的级联线索主从架构下,从节点日志会比较频繁地出现同步相关记录。全量同步会输出类似:12345:S 24 Feb 2025 10:05:00.123 * Full resync from master: abc...增量同步失败后再触发全量同步,会产生部分重同步失败的记录。这类问题的关键配置是 repl-backlog-size,默认 1M,太小的话断线期间写入量稍大就撑不住,主从只能全量重同步。我把这个值调大后,网络闪断基本都能通过部分重同步恢复。排查同步问题时,主从两个节点的日志要一起看。主节点日志里有 “Connection with replica lost” 之类的记录,从节点日志里则显示重试连接。只看一边容易误判方向。5.4 连接数异常与输出缓冲区问题连接数被打满时,日志里会出现:# Possible SECURITY ATTACK detected. It looks like somebody is sending us a lot of commands.这条日志出现,要么是业务方误用了连接池,要么是有人在进行密集命令发送。配合 maxclients 配置和客户端数量即可判断。另外还有输出缓冲区导致的从节点断连。主节点的 client-output-buffer-limit replica 设置不合理,从节点处理慢时缓冲区溢出,主节点主动断开连接。日志里表现为从节点频繁重连,主节点周期性打印 replica 连接断开。把 replica 的缓冲上限调大并设置硬性超时,问题就解决了。6. 常见问题速查:日志特征、配置根源与处理建议把高频问题整理成一张表,方便直接对照。实际排查时我建议按“日志特征 → 配置检查 → 处理动作”的顺序走,不要看到日志直接改配置,先确认配置是不是真的导致问题的根因。问题现象日志特征常见配置根源处理建议内存持续增长后写入失败无明显日志,慢查询增多maxmemory 未设置或偏小合理设置 maxmemory,调整淘汰策略RDB 持久化不生效fork: Cannot allocate memory内存碎片、overcommit 策略过严调整 vm.overcommit_memory,关闭 THP磁盘繁忙导致卡顿AOF fsync is taking too longappendfsync 策略过严或磁盘性能差调整 fsync 策略,优化磁盘主从频繁全量同步Partial resynchronization not possiblerepl-backlog-size 过小加大 repl-backlog-size无法建立外部连接日志无异常,客户端拒绝bind/protected-mode 配置不当检查监听地址与保护模式连接被频繁断开Client closed connectiontimeout 过短或连接池超时调大 timeout,检查客户端配置慢查询大量出现SLOWLOG GET 耗时高命令复杂度高或内存淘汰影响优化命令,拆分大 key数据重启后丢失日志无持久化记录未开启 AOF 且 save 条件未触发开 AOF,调整 save 策略这张表只能覆盖常见场景,真正复杂的故障往往叠加多种因素。我的习惯是,每出一个问题,就把当时的配置快照、日志片段、处理动作记成一条 backlog,后续再遇到类似日志能直接检索到历史处理方式。最后的实操体会说句实在话,配置日志这块东西,看起来是基础能力,但恰恰是很多线上问题的分水岭。我自己踩过几次坑之后,养成了一个习惯:每台 Redis 实例启动之前,先导出一份 CONFIG GET * 的完整配置快照,再设置好 loglevel、slowlog、logfile 三个日志相关配置,最后才让业务接入。变更配置后,不去看监控曲线,而是先盯日志有没有新出现的 # 和 - 行。还有一个细节想分享:CONFIG REWRITE 不是每次都可靠,配置文件权限不对或格式特殊时可能静默失败。所以我每次 REWRITE 之后都会重新打开 redis.conf 看一眼,确认改动真的落盘了。这些小习惯不花多少时间,但能在关键时刻帮你省下好几个小时的排查时间。如果你现在正在为某个 Redis 问题头疼,建议先别急着搜报错,把日志和配置放到一起过一遍,大概率答案就在你手上。
接手 Redis 的人应该都有这种经历:查一个问题,翻配置、翻日志、翻监控,来回折腾半天,最后发现根因就藏在某一行 loglevel 设置或者一个没配好的 maxmemory 里面。所谓 Redis 配置和日志,表面上一个是“事前设定”,一个是“事后记录”,但在实际操作中它们根本拆不开——配置决定行为,日志暴露行为,而故障定位就是在两者之间反复对照的过程。我刚学 Redis 的时候,以为配置就是把 redis.conf 里几个参数改成推荐值,日志嘛,出错看一眼就行。直到有一次排查线上问题,翻了几小时日志才发现问题出在配置文件里一个不起眼的 save 参数上——那一刻我才明白:配置和日志不是两件事,而是同一件事的两面。这篇文章不打算复述官方文档,而是想从“配置怎么定、日志怎么读、两者怎么对得上”这条实操主线出发,把 Redis 配置和日志相关的内容串起来。适合自己搭过 Redis、但总觉得差点意思的开发者,也适合刚接手 Redis 运维、正在跟各种异常日志较劲的运维同学。1. 配置与日志:Redis 运维的一体两面为什么我把“配置”和“日志”放在一起讲?因为处理 Redis 问题的时候,配置和日志从来不是独立的两条线。1.1 配置文件决定了日志里会出现什么配置是预期管理:内存多大、数据怎么持久化、允许谁连接、什么命令算慢。日志是现实反馈:实际占了多少内存、持久化成没成、谁连接失败、哪个命令把主线程卡住了。配置不对,日志里就会反复出现对应的异常;日志看不懂,再好的配置也不知道该往哪里调。举个最简单的例子:maxmemory 配得小,日志里可能看到慢查询增多,因为内存淘汰占用主线程;save 配得太勤,日志里就会出现大量后台保存记录,甚至触发 fork 失败;appendfsync 配成 always,磁盘慢的时候日志里会持续刷“AOF fsync is taking too long”。配置和日志的关系,就像愿望和现实的关系——不对比着看,问题永远是半个问题。所以我的建议是,不管是谁,拿到一台 Redis 实例之后要做两件事:先完整过一遍 redis.conf 的配置清单,再去看启动日志和运行日志。很多人习惯直接跳过配置去看日志,结果日志里提示的“无法保存”“内存不足”,根子全在配置上。1.2 redis.conf 的装载顺序和动态修改能力Redis 的配置来源有三个层次,从高到低分别是:命令行参数、配置文件、默认值。命令行里指定了配置,配置文件里的对应项就不会生效;配置文件里没写,就用编译时内置的默认值。启动 Redis 时如果没显式指定配置文件,Redis 用默认配置启动,那种裸奔状态最容易出问题。启动命令里用 -c 指定配置文件的路径:redis-server /etc/redis/redis.conf。运行时还可以用 CONFIG GET 和 CONFIG SET 动态查看和修改配置,不用重启。这里有个关键点:CONFIG SET 修改的是内存中的值,不会自动写到文件里。想让修改持久化,得再执行一次 CONFIG REWRITE,它会把当前有效的配置回写到 redis.conf 中,同时保留文件里原有的注释。不过要提醒一句,并非所有配置都支持动态修改。端口、日志文件路径这类影响运行时资源分配的配置项,CONFIG SET 往往无法生效。所以在搜“Redis 配置日志”相关内容时,你可能会看到别人用 CONFIG SET 修改慢查询阈值或者内存策略,但从来没人用 CONFIG SET 去改端口,因为根本改不动。配置优先级快速对照:配置来源优先级说明命令行参数最高覆盖配置文件与默认值配置文件 redis.conf次之覆盖默认值编译默认值最低被以上两层覆盖重要提示:线上变更配置,别急着 CONFIG REWRITE。先 CONFIG SET 观察一段时间,确认稳定后再写回文件,否则一旦写回有问题的配置,重启后很难快速回滚。2. 核心配置项解析:内存、持久化与安全Redis 配置项很多,但实际业务里高频被调整、又容易导致日志异常的就那么几类:内存、持久化、网络与安全。我逐个说清楚这些配置该怎么选,以及选错之后日志里会出现什么。2.1 内存上限与淘汰策略:先想清楚 Redis 装得下什么maxmemory 默认在 64 位系统下是 0,表示不限制内存使用,这个状态跑在开发环境没问题,上生产就危险了,内存一旦被数据占满,Redis 进程直接被系统 OOM Kill,日志里基本只会留下操作系统的记录,Redis 自身来不及打任何东西。配置 maxmemory 要结合机器物理内存和业务数据量来算:比如机器内存 16G,系统和其他进程预留 4G,Redis 最多分到 12G,那么 maxmemory 设为 10G 比较稳妥,留 2G 余量给 fork 子进程和内存碎片。别把 maxmemory 当作“刚好存下所有数据”的目标,而是当作“绝对不能超过”的底线。内存满了之后的行为由 maxmemory-policy 控制。这是 Redis 配置里最关键的策略项之一,选择不同策略,直接影响日志中是否会出现命令报错。策略行为适用场景noeviction不做任何淘汰,写命令直接报错需要严格保障数据不丢的场景allkeys-lru从所有 key 中淘汰最近最少使用的纯缓存场景,最常见volatile-lru仅从设置了过期时间的 key 中淘汰缓存+持久化混合场景allkeys-random随机淘汰任意 key访问热度差异不明显时volatile-random随机淘汰带过期时间的 key数据可重建场景volatile-ttl优先淘汰剩余存活时间短的 key对过期时间敏感的缓存我的经验是,业务侧如果接受缓存天然淘汰,优先 allkeys-lru;如果 Redis 里既有缓存数据又有不能丢的数据,noeviction 配合合理的容量规划更安全。还有一种常见组合是 volatile-lru + 所有 key 都设置过期时间,基本等价于 allkeys-lru。内存淘汰还有一点要留意:maxmemory 不设或者设置不合理,日志里不会直接写“内存淘汰了某个 key”,Redis 的淘汰是静默的,只有在慢查询日志里才能间接看到写命令变慢。所以排查内存问题,光看日志是不够的,还要配合 INFO memory 和监控曲线。2.2 持久化配置:RDB 与 AOF 的取舍Redis 持久化有 RDB 快照和 AOF 追加日志两种形式,配置上各有几个关键参数。RDB 靠 save 参数触发,比如默认配置里有这么一段:save 3600 1 save 300 100 save 60 10000意思是 3600 秒内至少有 1 次写操作、300 秒内至少有 100 次写操作、60 秒内至少有 10000 次写操作时,执行一次快照。RDB 文件紧凑、恢复快,但数据丢失窗口大,两次快照之间的写入在宕机时都会丢。AOF 通过 appendonly yes 开启,appendfsync 控制刷盘策略:always 每次写都刷盘,最安全但性能最低;everysec 每秒刷一次,是性能和可靠性的折中;no 交给操作系统决定刷盘时机,数据丢失风险大。线上我一般选 everysec,追求极致安全的场景才用 always。Redis 4.0 之后默认开启混合持久化,也就是 aof-use-rdb-preamble yes,AOF 文件开头用 RDB 格式记录已有数据,后面用 AOF 格式记录增量,兼顾了加载速度和数据完整性。这个配置对日志最直接的影响是重写时的日志关键词,混合模式下日志里的 RDB 和 AOF 相关记录会交替出现。2.3 网络与安全配置:暴露面越小越好bind、protected-mode、requirepass 这三个配置直接决定谁能连上你的 Redis。bind 默认绑定本地回环地址,注释掉之后 Redis 会监听所有网卡,这对局域网环境方便,但一旦服务器有公网 IP,Redis 相当于裸奔在公网上。protected-mode yes 是 Redis 的自我保护机制:如果没有设置 requirepass,且没有显式设置 bind 时,Redis 只接受本机回环连接。这层保护很关键,但也有副作用——很多人配了 bind 指向内网 IP,却忘了 protected-mode 会因此放行,导致公网也能访问。我的建议很简单:生产环境 bind 只写内网网卡 IP 或回环地址,requirepass 必须设置,密码用高强度随机串。日志里如果出现 “Unauthorized connection” 或大量来自陌生 IP 的连接,先去查这三个配置是不是太宽松了。timeout 和 tcp-keepalive 属于连接层面的细节配置。timeout 设置空闲连接多久后被关闭,默认 0 永不过期,容易累积空闲连接。tcp-keepalive 默认 300 秒,建议保留默认值,过短会产生大量探测包,过长会导致失效连接残留。这两个参数配置不当,日志里会看到大量连接被异常断开,表现为客户端突然报超时。3. 日志体系:级别、输出与格式解读配置看得差不多了,说说日志本身。Redis 日志虽然格式简单,但信息量很大,学会看日志级别和格式,很多问题能一眼定位。3.1 日志级别:不是越大声越好loglevel 有四个级别:debug、verbose、notice、warning。默认是 notice,生产环境也是 notice 为主。级别输出内容适合场景debug最详细,包含每个连接、每条命令级别的信息开发环境调试,生产坚决不用verbose较详细,包含连接建立与关闭等本地测试notice常规提示,启动、持久化、同步事件生产默认warning只有关键警告和错误磁盘紧张、日志量受限时我在生产环境见过有人把 loglevel 调成 debug 想排查问题,结果日志一小时写满几个 G,直接把磁盘撑爆,主进程反而因为磁盘满而卡顿。排查问题应该用慢查询日志和监控工具,而不是靠 debug 级别“大海捞针”。3.2 日志输出位置与收集方式logfile 配置指定日志文件路径,常见设置为 /var/log/redis/redis-server.log。如果 logfile 为空字符串,日志会输出到标准输出 stdout,这个设计在容器部署时非常有用,系统会把 stdout 收集到 docker logs 里,日志收集就交给容器平台统一处理。用 systemd 管理 Redis 时,如果 logfile 配置为空,日志会进入 journald,可以直接用 journalctl -u redis-server 查看。这种场景下别再去 /var/log 下面找文件,很多新手在这里卡半天。日志文件需要轮转,不然会无限膨胀。最省事的方式是配置 logrotate,我一般按天轮转、保留 30 份左右。配置参考如下:/var/log/redis/redis-server.log { daily rotate 30 compress delaycompress missingok notifempty copytruncate }注意 copytruncate 这个参数很关键,Redis 持有日志文件的文件句柄,直接 rename 会导致 Redis 继续往旧文件写,只有 copytruncate 能先复制再清空原文件。3.3 读懂 Redis 日志的时间戳与角色标识一条典型的 Redis 日志长这样:12345:M 24 Feb 2025 10:00:00.123 * Ready to accept connections拆开看:12345 是进程 PID,M 是角色标记,后面是时间戳,* 是消息类型,最后是内容。角色标记的含义:M:主节点(Master)S:从节点(Replica/Slave)C:子进程(比如 RDB 或 AOF 后台子进程)X:哨兵(Sentinel)消息类型符号也值得记一下:* 表示普通信息,- 表示警示信息,# 表示错误信息。排查故障时优先看 # 和 - 开头的行,* 多数是启动过程和常规事件。启动日志的序列也很有规律:先是加载配置文件,然后设置 signal handler,接着打开 TCP 端口监听,如果配置了持久化会尝试加载已有数据,最后打出一句 Ready to accept connections。看到这句说明 Redis 基本启动成功,在这之前如果日志中断,问题就在对应的环节。4. 慢查询日志:定位命令级瓶颈的关键很多人以为慢查询日志要额外配置什么插件,其实 Redis 内置了,只是默认阈值设置使大部分环境下不会被触发。慢查询日志记录的是执行时间超过阈值的命令,是排查性能问题时利用率最高的日志。4.1 慢查询的配置与阈值选择两个核心配置:slowlog-log-slower-than 10000 slowlog-max-len 128slowlog-log-slower-than 单位是微秒,默认 10000 微秒也就是 10 毫秒。注意单位是微秒,很多人想配置成 1 毫秒写成 1,结果所有命令都进慢查询日志,数据量瞬间爆炸。想配成 1 毫秒应该写 1000。slowlog-max-len 是内存中最多保存多少条慢查询记录,默认 128。慢查询日志是存内存的,不是写文件,所以这个上限要控制,太小查不到历史,太大又占内存。一般设置 256 到 1024 之间足够。阈值选择上,要根据业务容忍度调整。读多写少的缓存场景,1 毫秒以上的命令已经算慢;批量操作的场景,单条命令几十毫秒可能也正常。我的建议是先从 10 毫秒开始,结合业务监控逐步下调,不要一开始就追求极致。4.2 慢查询的读取与分析命令行下用 SLOWLOG GET 查看最近记录,SLOWLOG LEN 查看记录条数,SLOWLOG RESET 清空记录。返回结果包含四个核心字段:命令执行时间戳、执行耗时(微秒)、命令参数、客户端地址等。实操中我的习惯是先用 SLOWLOG LEN 看数量,再用 SLOWLOG GET 10 取最近 10 条,重点看命令本身和耗时。如果慢查询集中在 KEYS、SMEMBERS 这类 O(N) 复杂度的命令,说明业务侧数据结构使用不合理;如果集中在 SET 这类简单命令,可能是机器负载过高或者持久化刷盘拖累。有一个细节:慢查询日志里记录的是“命令执行耗时”,不包括网络传输和排队时间。也就是说,客户端觉得 Redis 很慢,但慢查询日志里没记录,问题可能出在网络、客户端连接池或者 Redis 主线程被其他操作阻塞。这时候要去看 CPU 状态和 INFO commandstats,别只盯着慢查询日志。注意:SLOWLOG 输出的命令参数会直接展示键名,如果键名包含敏感业务字段,排查日志时要避免把完整输出分享给无关人员。5. 日志驱动的典型故障排查实录配置和日志的最终价值,都在故障定位上。我挑几个最常遇到的场景,把日志特征和排查思路完整走一遍。5.1 内存膨胀与被动淘汰:日志里的“无声警告”场景:Redis 使用率持续上涨,业务侧反映部分缓存读取落空,数据被刷新。排查时先看 INFO memory,关注 used_memory、used_memory_peak、maxmemory 三个值。实际占用接近 maxmemory 后,Redis 会根据淘汰策略开始清理 key,这个过程默认不打印日志。唯一能感知到的是慢查询日志中逐渐出现 SET/GET 命令耗时增加,因为淘汰本身消耗主线程时间。这类问题的配置根源,往往就是 maxmemory 没设或者设置过大,以及 maxmemory-policy 与业务方预期不一致。我之前处理过一个缓存消失的案例,配置是 noeviction,内存满了之后写命令直接报错,但外部监控只看命中率,忽略了错误率,排查半天才定位到配置上。排查套路:先 CONFIG GET maxmemory 和 maxmemory-policy 确认配置是否符合预期,再看 used_memory 与峰值比例。如果接近上限,按业务 key 大小估算容量,要么扩容,要么优化数据冗余。5.2 fork 失败与持久化中断:日志里的高危信号Redis 做 RDB 快照或 AOF 重写时,需要 fork 一个子进程。fork 失败时会打这样一条日志:67215:M 24 Feb 2025 10:00:05.123 # Can't save in background: fork: Cannot allocate memory这里 Cannot allocate memory 不一定是物理内存不够,多数情况是操作系统的 overcommit 策略不允许进程地址空间一次性映射。解决手段是设置 vm.overcommit_memory 为 1,并检查透明大页是否开启,后者常导致 fork 后内存占用翻倍。我见过最离谱的情况是,Redis 实例本身只占 2G 内存,但系统 vm.overcommit_memory 设为默认的 0,加上连续内存碎片,fork 一直失败,RDB 从未执行成功过。查日志才明白为什么持久化文件一直是好几天前的。另一个高频日志是 AOF fsync 慢:67215:M 24 Feb 2025 10:00:30.456 * Asynchronous AOF fsync is taking too long (disk is busy?). Writing the AOF buffer may slow down Redis.这条说明磁盘 IO 跟不上写入速度,通常发生在机械盘或共享存储上。应对手段包括降低 appendfsync 频率、升级磁盘、错峰执行 AOF 重写。看到这条日志别急着加机器,先看磁盘 IO。5.3 主从同步异常:日志中的级联线索主从架构下,从节点日志会比较频繁地出现同步相关记录。全量同步会输出类似:12345:S 24 Feb 2025 10:05:00.123 * Full resync from master: abc...增量同步失败后再触发全量同步,会产生部分重同步失败的记录。这类问题的关键配置是 repl-backlog-size,默认 1M,太小的话断线期间写入量稍大就撑不住,主从只能全量重同步。我把这个值调大后,网络闪断基本都能通过部分重同步恢复。排查同步问题时,主从两个节点的日志要一起看。主节点日志里有 “Connection with replica lost” 之类的记录,从节点日志里则显示重试连接。只看一边容易误判方向。5.4 连接数异常与输出缓冲区问题连接数被打满时,日志里会出现:# Possible SECURITY ATTACK detected. It looks like somebody is sending us a lot of commands.这条日志出现,要么是业务方误用了连接池,要么是有人在进行密集命令发送。配合 maxclients 配置和客户端数量即可判断。另外还有输出缓冲区导致的从节点断连。主节点的 client-output-buffer-limit replica 设置不合理,从节点处理慢时缓冲区溢出,主节点主动断开连接。日志里表现为从节点频繁重连,主节点周期性打印 replica 连接断开。把 replica 的缓冲上限调大并设置硬性超时,问题就解决了。6. 常见问题速查:日志特征、配置根源与处理建议把高频问题整理成一张表,方便直接对照。实际排查时我建议按“日志特征 → 配置检查 → 处理动作”的顺序走,不要看到日志直接改配置,先确认配置是不是真的导致问题的根因。问题现象日志特征常见配置根源处理建议内存持续增长后写入失败无明显日志,慢查询增多maxmemory 未设置或偏小合理设置 maxmemory,调整淘汰策略RDB 持久化不生效fork: Cannot allocate memory内存碎片、overcommit 策略过严调整 vm.overcommit_memory,关闭 THP磁盘繁忙导致卡顿AOF fsync is taking too longappendfsync 策略过严或磁盘性能差调整 fsync 策略,优化磁盘主从频繁全量同步Partial resynchronization not possiblerepl-backlog-size 过小加大 repl-backlog-size无法建立外部连接日志无异常,客户端拒绝bind/protected-mode 配置不当检查监听地址与保护模式连接被频繁断开Client closed connectiontimeout 过短或连接池超时调大 timeout,检查客户端配置慢查询大量出现SLOWLOG GET 耗时高命令复杂度高或内存淘汰影响优化命令,拆分大 key数据重启后丢失日志无持久化记录未开启 AOF 且 save 条件未触发开 AOF,调整 save 策略这张表只能覆盖常见场景,真正复杂的故障往往叠加多种因素。我的习惯是,每出一个问题,就把当时的配置快照、日志片段、处理动作记成一条 backlog,后续再遇到类似日志能直接检索到历史处理方式。最后的实操体会说句实在话,配置日志这块东西,看起来是基础能力,但恰恰是很多线上问题的分水岭。我自己踩过几次坑之后,养成了一个习惯:每台 Redis 实例启动之前,先导出一份 CONFIG GET * 的完整配置快照,再设置好 loglevel、slowlog、logfile 三个日志相关配置,最后才让业务接入。变更配置后,不去看监控曲线,而是先盯日志有没有新出现的 # 和 - 行。还有一个细节想分享:CONFIG REWRITE 不是每次都可靠,配置文件权限不对或格式特殊时可能静默失败。所以我每次 REWRITE 之后都会重新打开 redis.conf 看一眼,确认改动真的落盘了。这些小习惯不花多少时间,但能在关键时刻帮你省下好几个小时的排查时间。如果你现在正在为某个 Redis 问题头疼,建议先别急着搜报错,把日志和配置放到一起过一遍,大概率答案就在你手上。