Redis 7配置的三个隐藏陷阱

我给 Redis 7 设了 maxmemory 2gb,跑压测期望内存到上限后自动 LRU 淘汰老 key。

10 分钟后 docker stats

erlang 复制代码
CONTAINER   MEM USAGE       LIMIT
redis       5.2GiB / 8GiB   64.79%

更离谱的是 CONFIG REWRITE 明明返回 OK,重启容器后配置全丢。查了三小时,发现不是 Redis 的 bug,是三个设计默认值叠在一起把我骗了。


坑 1:CONFIG SET 只改运行时,不写文件

我以为 5 分钟能搞定的事:

sql 复制代码
docker exec -it redis redis-cli
CONFIG SET maxmemory 2gb
CONFIG SET maxmemory-policy allkeys-lru
CONFIG REWRITE

回车,看着没毛病。重启容器后查:

ruby 复制代码
127.0.0.1:6379> CONFIG GET maxmemory
1) "maxmemory"
2) "0"

0?我刚明明设了 2gb,而且也 REWRITE 了。

盯着这行看了一会儿才反应过来:CONFIG SET 改的是运行时内存中的配置 ,不持久化到文件。要持久化得靠 CONFIG REWRITE 或者手动改 redis.conf

但 REWRITE 我也执行了啊。


坑 2:CONFIG REWRITE 返回 OK,但静默失败

进容器看 conf 文件:

bash 复制代码
docker exec -it redis cat /usr/local/etc/redis/redis.conf | grep maxmemory
复制代码
maxmemory 2gb
maxmemory-policy allkeys-lru

文件里明明写着 2gb,但 CONFIG GET 返回 0。绕了一圈才想通:这个 redis.conf 是从宿主机 bind mount 进容器的,容器对它有读权限,但 REWRITE 不一定能写回去

宿主机上的文件 owner 是我自己,容器里的 redis 进程是 UID 999,跨过 mount 直接写 host 路径,权限不对。

CONFIG REWRITE 命令也没报错。Redis 文档里说:

If REWRITE fails (e.g. cannot write to the file), Redis returns an error.

我手动跑了一遍:

ruby 复制代码
127.0.0.1:6379> CONFIG REWRITE
OK

返回 OK,文件实际没变。翻了一圈 issue,发现 Redis 在某些 mount 场景下会把"找不到原 conf 路径"当成"没用 conf file 启动",直接默默吞掉 REWRITE。具体什么场景我没完全摸清,反正这次它确实没写成,但也确实不报错。

OK 不等于成功。这是排查时最耽误时间的地方。


坑 3:maxmemory-policy 默认是 noeviction(不是 LRU)

第二天我把 conf 文件直接在 host 上改对,docker compose restart 后 CONFIG GET 也对了:

ruby 复制代码
127.0.0.1:6379> CONFIG GET maxmemory
1) "maxmemory"
2) "2147483648"

看着 OK。跑压测,内存涨到 2gb 后 Redis 没驱逐 key,直接抛 OOM:

bash 复制代码
OOM command not allowed when used memory > 'maxmemory'.
ruby 复制代码
127.0.0.1:6379> CONFIG GET maxmemory-policy
1) "maxmemory-policy"
2) "noeviction"

我之前 CONFIG SET 设的 allkeys-lru,容器重启之后也丢了。redis.conf 文件里我没加 maxmemory-policy allkeys-lru,默认就是 noeviction ------ 达到内存上限直接拒绝写,不驱逐任何 key

我以为"设了 maxmemory 就自动 LRU"。错。maxmemory 限制内存,maxmemory-policy 决定到达上限怎么办。两个独立配置,默认值是"啥也不淘汰,直接拒绝"。


三个坑叠加:排查时互相掩盖

每一个单独都好查。三个堆在一起,debug 路径变成:先怀疑压测脚本 → 再怀疑 Docker 内存 limit → 最后才回到 Redis 自己。

表格

你看到的 你以为的 实际发生的
CONFIG SET maxmemory 2gb 配置已生效 只改了运行时,重启就丢
CONFIG REWRITE 返回 OK 已写回文件 mount 权限问题,静默失败
内存涨到 2gb 开始 LRU 淘汰 noeviction 默认拒绝写入,直接 OOM

单看任何一个都好查。三个叠在一起,你会先怀疑压测脚本、再怀疑 Docker、最后才回到 Redis。


现在 conf 长啥样

就四行,跟容器一起初始化,运行时不再用 CONFIG SET 改:

perl 复制代码
# redis.conf
maxmemory 2gb
maxmemory-policy allkeys-lru
appendonly no
save ""

appendonly no + save "" 是把 AOF 和 RDB 都关掉,纯当缓存用。学习环境不需要持久化,关掉省 IO 也省排查路径。生产环境另说,但单机搞开发没必要扛着持久化跑。

原则:配置文件 single source of truth,运行时命令只用来临时调试,不信任 CONFIG REWRITE

每加一个 Redis 实例,conf 复制这四行,改 maxmemory 大小,完事。


下次起 Redis 直接复制

单机学习环境的最小可用配置:

perl 复制代码
maxmemory 2gb
maxmemory-policy allkeys-lru
appendonly no
save ""

下次配 Redis,先把 maxmemory-policy 显式写进 conf,别相信默认值。这是单字符串就能搞定的事,但默认值挺害人。

CONFIG REWRITE 我现在直接当不存在。

相关推荐
Ting-yu1 小时前
Spring AI Alibaba零基础速成(2) ---- Ollama安装与使用
java·后端·spring·ai
qq_5470261791 小时前
SpringBoot + Redis 电商秒杀完整方案
spring boot·redis·后端
会编程的吕洞宾1 小时前
Spring_Boot_3_3_的___Transactional__
java·后端·spring
阿聪谈架构1 小时前
第11章:结构化输出与数据提取 —— 让 AI 直接返回你想要的数据格式
人工智能·后端
神奇小汤圆1 小时前
Java面试八股文+场景题+答案,100万字精华版,全网仅此一份
后端
数据仓库搬砖人2 小时前
XGBoost 调参指南
后端
学以智用2 小时前
.NET Core 仓储模式(Repository Pattern)完整教程
后端·.net
叫我少年2 小时前
Quartz.NET 调度框架:从入门到封装实战
后端
Java编程爱好者2 小时前
MySQL事务实战:MySQL实例 · 隔离级别 · InnoDB实现机制
后端