slave-read-only yes是硬性拦截层,命令解析阶段即拒绝所有写操作,不进入执行流程;所谓“临时写入”在语义上不成立,因连内存写入都未发生。

不能写入任何数据,临时也不行。 slave-read-only yes 是硬性拦截层,只要生效,所有客户端(除特定权限/连接方式外)执行 SET、DEL、INCR 等写命令都会立即返回 (error) READONLY You can't write against a read only replica. —— 不分“临时”“持久”“内存级”,Redis 根本不进入执行阶段。
为什么“临时写入”在语义上就不成立
Redis 从节点的写操作不是“先写再丢”,而是被配置直接拒掉。所谓“临时数据”,通常指未落盘、可被覆盖或重启即失的数据;但这里连内存写入都未发生。主从复制是单向命令流,从节点没有本地事务上下文,也没有“暂存区”供绕过只读限制。
-
slave-read-only在命令解析阶段就触发拒绝逻辑,比EXEC、WATCH或EXPIRE的生命周期控制更前置 - 即使你用
DEBUG POPULATE或MODULE LOAD加载自定义命令,只要该命令产生写效果,同样被拦截(除非模块以管理员权限绕过 ACL) - 不存在“先设
slave-read-only no→ 写点东西 → 再设回yes”的窗口期安全做法:两次CONFIG SET之间写入的数据已污染状态,且无法自动清理
哪些情况看似能写,其实是配置或权限漏洞
出现“从库能写”的现象,基本不是 slave-read-only 失效,而是以下某处没对齐:
- 配置未生效:用
CONFIG SET slave-read-only yes动态设置后,没检查CONFIG GET slave-read-only是否真返回"yes";或者容器重启导致 redis.conf 里没写死该配置,又没挂载配置卷 - ACL 权限覆盖:Redis 6+ 启用了
requirepass和用户权限体系,若连接用户有+set或+@all权限,会跳过slave-read-only检查(权限优先级更高) - 本地连接绕过:某些旧版本(如
Redis )对127.0.0.1连接不强制只读,必须用非本地地址(如redis-cli -h 192.168.1.10)实测 - 误把
replica-read-only当新名儿用了:Redis 5.0+ 开始推荐用replica-read-only替代slave-read-only,但两者并存;如果只改了新配置项而旧项仍为no,实际生效的还是旧项
INFO replication 和 CONFIG GET 的关键验证顺序
光看 INFO replication 里的 slave_read_only:1 不够,必须组合验证:
- 执行
CONFIG GET slave-read-only和CONFIG GET replica-read-only—— 两个都得是"yes" - 执行
INFO replication | grep role确认输出是role:slave,而非role:master(避免故障转移后角色未更新) - 用非本地 IP 连接(如
redis-cli -h $SLAVE_IP -p 6379),执行SET test 1,必须收到READONLY错误 - 若启用了 ACL,用
ACL LIST查当前用户权限,确认不含+set、+@write或+@all
真正容易被忽略的是:配置项生效时机和 ACL 权限的隐式覆盖。很多团队只改了 redis.conf 却忘了容器启动参数是否覆盖了它,或升级到 Redis 7 后沿用旧 ACL 规则,结果 slave-read-only yes 形同虚设——这不是功能缺陷,而是部署链路上的断点。











