Redis 的 redis.conf 是所有线上实例的起点。我做运维这些年,接手新项目时第一件事永远不是看代码,而是先把这个文件拉出来读一遍——一多半的事故隐患都藏在几十行看似普通的配置项里。这篇文章会把 redis.conf 里真正影响生产的配置重新拆一遍,包括启动加载逻辑、网络与安全、RDB/AOF 持久化、内存淘汰、主从复制和性能调优,同时把我在实际维护中踩过的坑一起写出来。无论你刚接触 Redis,还是已经在线上维护过一段时间,这份详解都值得花十分钟过一遍。
1. 配置文件结构与加载逻辑:先从启动时把顺序搞明白
1.1 配置文件位置与 Redis 的启动加载顺序
很多新手对 redis.conf 的第一反应是“文件在哪儿”。安装方式不同,路径差别很大:源码编译时默认可能在源码目录,用系统包管理安装时通常在/etc/redis/redis.conf,用 docker 镜像时可能又在/usr/local/etc/redis/redis.conf。与其靠记忆,不如直接问运行中的实例。执行redis-cli INFO server,输出里的config_file就是当前实例实际加载的配置文件路径,这比到处find靠谱得多。
Redis 启动时的配置来源主要有三个:命令行参数、配置文件、运行时的CONFIG SET。优先级按“生效时机”理解最清楚:启动时,命令行参数会覆盖配置文件里同名的指令;启动之后,CONFIG SET改的是内存里的运行时配置,不影响磁盘文件,除非主动执行CONFIG REWRITE写回。举个例子:
redis-server /etc/redis/redis.conf --port 6380只要命令行带着--port 6380,即使配置文件里写的是port 6379,最终监听的也是 6380。这个机制在排障时最容易坑人:明明配置文件里改了端口,怎么重启后还是老端口?十有八九是启动脚本里多了一行命令行参数。
还要注意一个常见误区:如果直接敲redis-server而不带任何参数,Redis 不会自动读取你可能改过的 redis.conf,而是按内置默认值启动。内置默认值一般是保护模式开启、没有持久化、没有密码、监听回环地址。看起来安全,但如果你以为“装好了就能直接用生产配置”,最后数据丢得悄无声息。
配置文件内部解析时,指令名是大小写不敏感的,Port 6379和port 6379等价,但值是否大小写敏感要具体看,比如密码、ACL 规则就敏感。同一个指令在文件里出现多次时,后面的会覆盖前面的。之前我排过一个诡异问题,就是 redis.conf 里appendonly no写在前面,后面某行又出现appendonly yes,结果重启后 AOF 突然开启,磁盘被日志写满。
1.2 动态修改与 CONFIG REWRITE 的边界
CONFIG GET和CONFIG SET是线上排查时最高频的命令,比如临时调大内存上限、临时改慢日志阈值,都可以不重启完成:
redis-cli CONFIG SET maxmemory 256mb redis-cli CONFIG GET maxmemory redis-cli CONFIG REWRITECONFIG REWRITE会把当前内存中生效的配置尽量写回 redis.conf,避免重启丢失。但“尽量”两个字很重要:它不会覆盖你文件里的全部原始注释,更不是万能的格式化工具。生产环境里我见过有人改完参数后忘记CONFIG REWRITE,隔了几天服务器重启,配置全部回到旧值,数据写入策略直接变化,引发了一轮线上抖动。
还有一类配置是动态修改不了的,例如bind、port、daemonize、dir这类启动期决定进程行为或端口的参数。不同版本对动态修改的支持范围有差异,最稳妥的方法是在调整前先执行CONFIG GET确认当前值,然后CONFIG SET试一次;如果报错,就老老实实改文件并重启。我的习惯是:凡是涉及网络监听、进程守护、磁盘路径的配置,一律走“改文件 + 平滑重启”的流程;凡是内存、日志、超时这类运行参数,才允许临时动态修改,并立刻记得CONFIG REWRITE或同步到配置管理平台。
2. 网络与安全模块:先把自己保护起来再说性能
2.1 bind、port、protected-mode 三者的配合关系
默认端口是port 6379,如果一台机器上跑多个 Redis 实例,需要分别指定不同端口,同时注意每个实例独立使用配置文件,避免日志、持久化文件、套接字路径互相覆盖。
bind决定 Redis 监听哪些网卡 IP。默认配置常见的是bind 127.0.0.1 -::1,也就是只监听本机回环地址,这样外部网络完全无法访问。如果服务器要提供给其他机器访问,就必须把内网 IP 加进去,比如:
bind 127.0.0.1 192.168.10.20我建议优先绑定具体内网 IP,而不是直接bind 0.0.0.0。0.0.0.0 意味着所有网卡都监听,如果这台服务器同时有外网 IP,就会把 Redis 直接暴露到公网,扫描工具分分钟就能发现。
protected-mode是 Redis 3.2 之后引入的保护机制,默认yes。它的行为逻辑比较绕,简单理解就是:当 Redis 没有设置密码,并且没有显式绑定时,只允许本机回环地址连接。很多人在这里踩坑——明明设置了bind 0.0.0.0,远程客户端却连不上,启动日志里报 warning,说当前处于 protected mode 且未设置密码,Redis 主动拒绝了非回环地址的连接。这不是故障,是保护机制在工作。
所以生产环境的安全组合一般有两种:
- 推荐方式:
protected-mode yes+requirepass或 ACL +bind到指定内网 IP。 - 内网隔离充分时的简化方式:
protected-mode no+requirepass强密码。
千万不要同时出现protected-mode no+ 空密码 +bind 0.0.0.0这种组合,那等于把数据库裸奔在网络上,被非法写入只是时间问题。
2.2 requirepass 与 ACL 用户权限配置
最简单的访问控制是在 redis.conf 里设置全局密码:
requirepass YourStrongPassword设置之后,客户端连接需要AUTH YourStrongPassword,主从复制也需要在从库配置masterauth。但单个requirepass有很明显的问题:所有客户端共用一个密码,无法区分业务和运维,无法限制某个人只能执行某些命令。
Redis 6 开始引入的 ACL 更值得关注。你可以在 redis.conf 里直接定义用户:
user default off user app on >app_password ~cache:* +get +set +del +exists +expire +ttl这段配置的含义是:默认用户关闭;新建一个名为 app 的用户,启用认证,密码为 app_password,只能操作cache:前缀的 key,只能执行白名单里的命令。这样即使业务密码泄露,能影响的也只是cache:*这一片空间,执行不了FLUSHALL,也碰不到其他业务的数据。
更规范的做法是把 ACL 规则单独放一个文件:
aclfile /etc/redis/users.acl用aclfile之后,修改用户权限不需要动 redis.conf,执行acl load就能重新加载。在线上实例比较多的情况下,这比把 ACL 写在主配置里好管理很多。
我自己维护 Redis 时有一个原则:业务用户只给最小必要权限,运维账号单独开一个+@all用户,并且不用redis-cli -a传密码,因为-a会把密码暴露在进程列表里,任何能执行ps的人都能看到。正确做法是用AUTH命令交互输入,或者通过REDISCLI_AUTH环境变量传递。
3. 持久化配置:RDB 与 AOF 的取舍和落地细节
3.1 RDB 快照触发条件与常见风险
Redis 默认开启 RDB 快照,redis.conf 里默认有这样三行:
save 3600 1 save 300 100 save 60 10000意思分别是:每 3600 秒内如果有至少 1 次写操作,触发一次快照;每 300 秒内如果有至少 100 次写操作,触发一次快照;每 60 秒内如果有至少 10000 次写操作,触发一次快照。这三个条件是“或”的关系,满足任意一个就执行BGSAVE。
如果业务不需要 RDB,可以这样显式关闭:
save ""注意save ""必须单独一行,不能写成save "" 3600 1。
RDB 的核心风险是数据丢失窗口。因为快照是周期性执行的,最后一次快照之后的所有写入,一旦进程崩溃或机器宕机,就全部丢失。比如刚才三个条件,极端情况下可能丢 60 秒甚至一个周期内的数据。对缓存场景这通常可以接受,但如果是订单、账务这类数据,就必须考虑 AOF。
另外要理解BGSAVE的细节:它会 fork 一个子进程,由子进程把内存数据写入临时 RDB 文件,写完再 rename 覆盖正式文件。fork 的一瞬间虽然用了操作系统的写时复制,但页表拷贝和 fork 本身依然会占用内存和 CPU。实际经验是:在内存占用接近物理内存上限的机器上触发 bgsave,很容易出现内存不足甚至 OOM。所以maxmemory不能只盯着数据大小,要兼顾 fork 开销。
RDB 相关还有一些常用配置:
dbfilename dump-6380.rdb dir /data/redis rdbcompression yes rdbchecksum yes多实例时必须让每个实例的 dbfilename 不同,否则两个进程会争抢同一个文件,导致快照互相覆盖。dir 路径要保证磁盘空间充足,目录权限是 redis 进程可写的,否则后台保存会失败,线上表现就是last_bgsave_status: err。
3.2 AOF 刷盘策略、重写机制与混合持久化
AOF 打开的方式是在 redis.conf 里设置:
appendonly yes appendfilename "appendonly.aof"AOF 会把每个写命令追加到文件末尾,恢复时就重放这些命令。核心决策点是appendfsync刷盘策略:
| 取值 | 行为 | 数据安全 | 性能影响 |
|---|---|---|---|
| always | 每次写命令都执行 fsync | 最安全,最多丢一次写命令 | 最差,写延迟明显上升 |
| everysec | 每秒 fsync 一次 | 最多丢 1 秒数据 | 折中,推荐 |
| no | 交给操作系统决定刷盘时机 | 可能丢较多数据 | 好,但不稳定 |
生产环境绝大多数场景选everysec。always更适合对数据安全极度敏感的小写量场景,但性能损失要提前压测;no的性能不一定更好,因为系统刷盘时机不可控,可能出现突发磁盘 IO。
AOF 文件会随着写入不断膨胀,所以 Redis 需要重写机制。默认配置:
auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb含义是:当 AOF 文件体积比上次重写时翻了一倍,并且总大小超过 64mb,Redis 自动触发BGREWRITEAOF。也可以手动执行:
redis-cli BGREWRITEAOF这里强烈建议开启混合持久化:
aof-use-rdb-preamble yes开启后,AOF 文件头部变成 RDB 格式的二进制快照,后面再追加增量写命令。好处是文件体积比纯 AOF 小很多,重启加载时不需要从头重放全部命令,恢复速度大幅提升。这个参数从 Redis 4.0 引入,之后的版本默认普遍开启,但如果你的实例是从老版本升级上来的,需要确认一下。
还有一个容易忽略的点:如果同时开启 RDB 和 AOF,Redis 启动时优先加载 AOF,而不是 RDB。原因很简单,AOF 通常比 RDB 多包含更新的数据。如果 AOF 文件损坏,还可以用redis-check-aof工具修复,或者设置aof-load-truncated yes允许加载截断文件,但要清楚会丢失文件尾部一段数据。
4. 内存上限与淘汰策略:别让 Redis 变成 OOM 炸弹
4.1 maxmemory 设置依据与监控指标
redis.conf 里maxmemory默认是 0,64 位系统下 0 表示不限制。不限制意味着 Redis 可以一直增长直到把物理内存吃光,然后被系统 OOM Killer 杀掉,或者进入长时间 swap 导致性能崩溃。生产环境必须给这个参数设值。
设置多少合适,没有标准答案,但有几个经验方向。纯缓存场景,目标是把热点数据全部放进内存,通常会设置为物理内存的 60% 到 80%,剩下的留给操作系统 page cache、fork、临时缓冲。既做存储又做缓存,或者同时开了 AOF/RDB 的实例,要更保守一点,50% 到 70% 比较常见。
更精确的方式是看监控指标。执行:
redis-cli INFO memory重点关注几个值:used_memory是 Redis 分配器实际使用的内存,used_memory_rss是进程向操作系统申请的物理内存,mem_fragmentation_ratio是 RSS 与 used_memory 的比值。正常情况下比值在 1 到 1.5 之间;超过 1.5 说明内存碎片比较严重,可以考虑开启自动碎片整理;小于 1 说明使用了 swap,这是很危险的信号,需要马上介入。
举个例子:一台 32GB 内存的服务器,如果used_memory常年 20GB,设置maxmemory 24gb看起来还有 4GB 余量,但在执行 BGSAVE fork 时,瞬间需要更多可用内存,再加上 RSS 可能比 used_memory 高,24GB 就显得很紧张。这类机器我会把 maxmemory 压到 20GB 左右,同时关注maxmemory_policy能不能及时腾出空间。
配置写法:
maxmemory 20gb maxmemory-policy allkeys-lru maxmemory-samples 104.2 八种淘汰策略怎么选
maxmemory-policy决定了内存到达上限后,写入命令是继续执行还是报错,以及如何选择 key 淘汰。Redis 官方策略主要分三类:
第一类是不淘汰。noeviction表示内存满了之后,所有会导致内存增长的写命令直接返回错误,比如set、lpush都会失败,但读命令和删除命令仍可用。适合数据量大、不能丢 key 的存储型业务,代价是写入不可用,需要业务方做好降级。
第二类是只从设置了过期时间的 key 里淘汰。包括volatile-lru、volatile-lfu、volatile-random、volatile-ttl。这类策略适合 key 空间里有部分长期不过期的数据,希望优先清掉过期的 key 给新数据腾空间。要注意:如果所有 key 都没有设置 TTL,这类策略一个 key 都淘汰不了,效果等同于 noeviction,内存照样会被写满。
第三类是全局淘汰。包括allkeys-lru、allkeys-lfu、allkeys-random。这类策略不管 key 有没有 TTL,一视同仁地选淘汰对象,适合通用缓存。
具体选型逻辑可以参考这张表:
| 策略 | 淘汰范围 | 适用场景 |
|---|---|---|
| noeviction | 不淘汰 | 数据不可丢失,写入失败可降级 |
| allkeys-lru | 所有 key | 常规缓存,最近最少使用优先淘汰 |
| allkeys-lfu | 所有 key | 热点数据集中,访问频率差异明显的场景 |
| volatile-lru | 带 TTL 的 key | 混合业务,保护不淘汰的长期 key |
| volatile-lfu | 带 TTL 的 key | 同上有访问频率区分 |
| volatile-ttl | 带 TTL 的 key | 快速清理即将过期的 key |
| allkeys-random | 所有 key | 数据访问均匀,淘汰任意 key 都可接受 |
| volatile-random | 带 TTL 的 key | 同上,限定范围 |
maxmemory-samples是 LRU/LFU 的采样样本数,默认 5。样本越多,淘汰“最冷”数据的准确度越高,但 CPU 开销也越高。追求极致命中率可以调到 10,大多数场景 5 就够。
还有一个容易被忽略的点:淘汰动作本身会消耗 CPU,如果内存压力很大,Redis 会忙于逐出 key,写延迟反而升高。配合后面会讲的lazyfree-lazy-eviction yes,可以把逐出操作放到后台异步执行,降低主线程阻塞风险。
5. 主从复制与高可用配置:从单机走向集群
5.1 复制基础配置与主从延迟
主从复制是最常见的高可用基础架构。从库的 redis.conf 里配置:
replicaof master-ip 6379 replica-read-only yes从 Redis 5 开始官方统一用replicaof,老版本的slaveof仍然兼容,但新项目没有必要再用旧关键字。replica-read-only yes是从库只读,强烈建议保持开启;如果因为误操作把从库设置成可写,会出现主从数据不一致,而且很难追查。
如果主库配置了requirepass,从库还要设置:
masterauth YourStrongPassword很多人主从同步失败,日志里反复出现NOAUTH Authentication required,原因就是主库加了密码但从库没有配置 masterauth。还有使用 ACL 的场景下,从库要用一个具备复制权限的用户认证,不是所有用户都可以执行复制协议。
主从复制分为全量同步和部分同步。全量同步发生在新从库首次连接,或者从库断线时间太长导致增量数据丢失时。全量同步期间,主库要 bgsave 生成 RDB,然后通过网络发给从库,从库清空自身数据再加载。大数据量下这个过程可能持续几分钟甚至更久,期间主库的磁盘 IO 和网络带宽都会明显上升。
从库的延迟可以通过命令观察:
redis-cli -p 6380 INFO replication重点关注master_link_status是不是up,以及master_last_io_seconds_ago,这个值表示从库多久没收到主库的心跳了。如果在业务高峰期这个值持续增大,说明主从之间的网络或主库自身可能有问题。
5.2 repl-backlog、diskless sync 等进阶参数
repl-backlog-size是主库为每个从库保留的最近写入命令缓冲区,默认 1mb。它的作用是在从库短暂断线后,主库可以从 backlog 里把增量发送给从库,避免做全量同步。
backlog 太小很容易被覆盖。举个例子:主库写入速率 2MB/s,从库断开 30 秒,这期间主库产生了 60MB 增量,默认 1mb 的 backlog 根本装不下,从库回来只能全量同步。所以生产环境建议根据写入速率估算,比如在这个例子中设置 64mb 或者更大。
repl-backlog-size 64mbrepl-diskless-sync是另一个值得关注的参数。默认no,全量同步时主库先把 RDB 写到磁盘,再由子进程读文件发送给从库。如果改成yes,主库可以直接通过网络把 RDB 数据流发送给从库,省去磁盘读写。磁盘慢而网络快的场景提升明显,但有多个从库同时全量同步时会占用大量网卡带宽。相关参数repl-diskless-sync-delay默认 5 秒,让主库稍微等待一下,把多个从库的全量同步合并成一次,减少重复 bgsave。
其他几个复制相关参数:
replica-priority:哨兵选主时优先级,数字越小越优先,0 表示该从库永远不提升为主库。replica-serve-stale-data:从库与主库失联后,是否继续对外提供旧数据。yes表示可用性优先,no表示一致性优先。如果业务读到的数据不能是过期的,建议no,让客户端感知到故障,而不是默默读到旧值。repl-timeout:主从之间网络超时时间,默认 60 秒。跨机房复制时如果网络抖动明显,可以适当调大,但要权衡故障发现速度。
主从架构有一个天然问题:复制是异步的,所以从库的数据一定会有一小段延迟。做读写分离时,业务要能容忍读到延迟数据;如果完全不能容忍,就只能走单节点或者引入更复杂的强一致方案。
6. 性能与连接数优化:把 Redis 压到极限而不是压垮
6.1 连接数、timeout、tcp-backlog 与内核参数
高并发场景下最先触发的问题往往不是 CPU,而是连接数。maxclients默认 10000,表示 Redis 最多接受多少个客户端连接。但真实上限还要看系统文件描述符限制:
ulimit -n如果系统nofile只有 1024,那么 Redis 的 maxclients 就算设成 10000,实际能建立的连接也不会超过 1024 减去 Redis 自身占用的 fd。所以调整 maxclients 时必须同步调大系统的ulimit -n,比如设置为 maxclients 的两倍有余。
timeout默认 0,表示不主动断开空闲连接。如果业务里有大量不规范的客户端,连接建立后既不发命令也不关闭,连接数会越积越多。设置timeout 300可以让 Redis 在 300 秒后断开空闲连接,但对长连接应用要谨慎,一旦业务侧没有自动重连机制,就会看到大量连接报错。
tcp-keepalive默认 300,Redis 会周期性探测 TCP 连接是否存活。如果客户端异常断电,操作系统通过 keepalive 可以更快发现死连接并释放资源。这个参数一般保持 300 即可。
还有一个容易忽略的内核层面参数tcp-backlog。redis.conf 里的tcp-backlog 511对应的是内核 TCP 握手队列长度。连接请求量极大时,如果队列被占满,新连接会被内核直接丢弃,客户端看到的就是 connect timeout。要真正扛住高并发,还需要调整系统参数:
sysctl net.core.somaxconn=511 sysctl net.ipv4.tcp_max_syn_backlog=1024修改后重启 Redis 或确认配置生效,否则 redis.conf 里的 tcp-backlog 只是“单方面愿望”。
6.2 IO 多线程与内存碎片整理
Redis 6 引入 IO 多线程,核心目的是提高网络读写吞吐。默认情况下,Redis 主线程既要处理命令执行,也要负责网络读写,CPU 密集型业务下主线程很容易成为瓶颈。通过下列配置可以让部分网络 IO 交给额外线程:
io-threads 4 io-threads-do-reads yesio-threads设置为几,取决于机器 CPU 核数和实例负载。4 核以下机器不建议开启,因为线程切换和锁竞争会吃更多 CPU;高并发、大量并发连接的场景开启后收益明显。另外有一点要注意:Redis 命令执行仍然由单个主线程完成,IO 多线程只处理网络读写,所以它不会解决慢命令引起的阻塞问题。
以下经验来自我线上压测的对比:单个 Redis 实例、单客户端持续写入小 value 时,开启 IO 多线程几乎没有提升;但 100 个以上并发连接同时做大量 set/get 时,吞吐提升可以达到 30% 以上。如果你的连接数不高,可以先不开,别盲目堆线程。
内存碎片整理也是大内存实例的老大难。频繁更新 key、淘汰 key 后,内存碎片会逐渐积累,used_memory_rss远大于used_memory。Redis 提供自动整理:
activedefrag yes active-defrag-ignore-bytes 100mb active-defrag-threshold-lower 10 active-defrag-threshold-upper 100含义是:当碎片超过 100MB 且碎片率大于 10% 时开始整理,高于 100% 则认为碎片严重,加大整理力度。整理过程是后台执行的,但也会占用 CPU,如果业务对延迟极敏感,建议在低峰期手动整理或直接重启实例换干净内存。
大 key 删除也可能阻塞 Redis。删除一个几百 MB 的 key,即使只执行一个del,也可能让主线程卡顿几百毫秒。推荐在 redis.conf 里开启:
lazyfree-lazy-eviction yes lazyfree-lazy-expire yes lazyfree-lazy-server-del yes这样淘汰、过期、服务端主动删除都放到异步线程执行,主线程不会被大 key 拖死。业务代码在删除超大 key 时,也应该优先使用UNLINK而不是DEL。
7. 生产环境常见配置坑与排查实录
7.1 配置不生效与加载顺序问题
排障第一步永远是确认当前生效的配置。我见过太多次“改了没效果”,最后发现改的根本不是实例加载的那份文件。推荐两个命令:
redis-cli INFO server | grep config_file redis-cli CONFIG GET appendonly第一条告诉你实例加载了哪个配置文件,第二条告诉你当前生效的某个配置是什么。如果appendonly的值和文件里不一致,先检查是不是有命令行参数覆盖,再检查是不是有另一个appendonly出现在文件后面。
第二个高频问题是CONFIG SET改了但没CONFIG REWRITE。这种问题最隐蔽,因为改动当时生效,看起来一切正常,一重启就回到原始状态。如果用的是配置管理工具,建议所有持久化变更都通过统一流程修改 redis.conf,而不依赖手工CONFIG SET。
第三个问题是 redis.conf 里存在重复指令。文件很长的时候,前面的配置可能被后面的覆盖,但你眼睛盯着的是前面那一行,自然觉得“明明写对了”。可以用脚本统计每个指令出现次数,或者直接用有效的配置管理工具生成配置,避免手写文件时出现重复。
7.2 慢日志、延迟监控与资源限制实战
线上 Redis 变慢,我会按这个顺序排查:先看慢日志,再看延迟,最后看资源限制。
慢日志默认阈值是 10000 微秒,也就是 10 毫秒。可以调低一点,把问题提前暴露:
slowlog-log-slower-than 5000 slowlog-max-len 128执行:
redis-cli SLOWLOG GET 20慢日志里会显示执行时长、命令、参数、时间戳。看到一条执行几十毫秒的get,大概率不是命令本身慢,而是当时主线程被别的任务阻塞了,比如大 key 删除、AOF 刷盘阻塞、内存碎片整理。所以慢日志给出的不是答案,而是排查方向。
延迟方面,可以直接用客户端工具:
redis-cli --latency这个命令会持续统计往返延迟。如果平均值在 1ms 以内,但偶尔出现 50ms 以上的毛刺,结合慢日志和系统监控找原因。还要看:
redis-cli INFO commandstats它会列出每个命令的调用次数、总时长和平均时长,能快速定位是不是某类命令拖垮了整体性能。
资源限制层面,最常遇到的是连接数错误。日志或者客户端报ERR max number of clients reached时,除了看maxclients,还要检查系统 ulimit。另一个高频问题是INFO persistence里显示 bgsave 或 bgrewriteaof 失败,多半是磁盘空间不足或目录权限不对,先看df -h和ls -l是什么状态。
7.3 几个让我印象深刻的踩坑案例
案例一:内存上限设得太高,一执行 BGSAVE 就 OOM。当时那台机器 16GB 内存,Redis 数据 12GB,maxmemory 被设成 14GB。看起来还有 2GB 余量,但每次 bgsave fork 子进程时,系统内存瞬间紧张,直接触发 OOM Killer。解决办法是把 maxmemory 降到 10GB,并确认没有启用 swap,同时跟业务约定缓存 key 的过期策略。
案例二:AOF 文件涨到几个 GB,重启恢复要几分钟。原因是开启了 AOF,但aof-use-rdb-preamble一直是 no,导致启动时要从头重放所有写命令。改成 yes 并手动执行一次BGREWRITEAOF后,加载时间从几分钟降到几十秒。这个参数是持久化配置里最容易被低估的一个。
案例三:主从同步始终失败,日志反复出现NOAUTH。排查时主库明明能正常读写,从库的 masterauth 看起来也写了,最后发现从库配置文件里masterauth被放在replicaof前面,并且从库先启动连接主库时还没读到后面的配置。后来统一把主从认证参数放在复制指令前面固定位置,问题再没出现。
案例四:连接数没到 maxclients 就报错。系统 ulimit 默认 1024,Redis 配置 maxclients 5000,看起来不会超,但进程实际能打开的 fd 就 1024,所以连接数到 900 左右就开始报错。调大/etc/security/limits.conf并对齐 maxclients 后恢复。
最后分享一个我自己的习惯:每次调整 redis.conf 前,我会先用CONFIG GET *把当前运行参数完整导出保存,之后再做改动;重启前一定会先用新配置拉起一个临时实例,跑一遍redis-benchmark和INFO persistence,确认没有异常才敢灰度上线。Redis 的配置项很多,但每个参数背后都是取舍,理解它比套模板重要。希望这份详解能让你以后再看 redis.conf 的时候,第一反应不是“默认值能不能用”,而是“当前业务到底需要哪种策略”。