如何让Redis暂时停止接收新键,仅允许访问现有键?
Redis 禁止写入新键但保留现有键访问的实现方法
以下是几种Redis原生的实现方式,无需修改应用代码:
1. 基于内存限制与驱逐策略的折中方案
这个方法利用Redis的内存控制机制,阻止新键创建,同时允许对现有键的读写(只要不增加总内存占用):
- 首先查看当前Redis已使用内存:
INFO memory,找到used_memory字段的具体数值 - 设置
maxmemory为当前已使用内存值:CONFIG SET maxmemory <used_memory值> - 设置驱逐策略为
noeviction:CONFIG SET maxmemory-policy noeviction
当Redis内存达到maxmemory阈值后,所有会增加内存占用的操作都会被拒绝,包括创建新键、扩大现有键的内存占用(比如给已存在的字符串设置更长的值);但不增加内存的操作(比如覆盖现有字符串为相同长度的值、读取键、删除键)可以正常执行。
若要恢复正常写入,只需重置maxmemory为原配置(例如CONFIG SET maxmemory 0表示无内存限制)并调整驱逐策略即可。
2. 利用ACL规则限制创建类命令(Redis 6+)
Redis 6及以上版本支持ACL权限控制,可以直接拒绝所有会创建新键的命令组,但需注意:这个方法会限制所有创建新键的操作,同时也会阻止某些兼具修改与创建功能的命令(比如HSET在键不存在时会创建新键,因此会被拒绝,即便你只是想给已存在的哈希表添加字段):
- 查看当前默认用户的规则:
ACL GETUSER default - 更新默认用户规则,允许读、修改类命令,拒绝创建类命令:
ACL SETUSER default on ~* +@read +@write -@create - 保存ACL规则到配置文件(避免重启后失效):
ACL SAVE
@create命令组包含所有会创建新键的命令,比如SET(键不存在时)、HMSET(键不存在时)、LPUSH(键不存在时)等。
3. 使用Lua脚本实现精准拦截
如果需要更精准的控制——允许修改现有键,仅拒绝创建新键,可以通过Lua脚本包装写入命令,在执行前检查键是否存在:
- 创建自定义的
SAFE_SET脚本,仅当键存在时才执行SET操作:if redis.call('EXISTS', KEYS[1]) == 1 then return redis.call('SET', KEYS[1], ARGV[1], unpack(ARGV, 2)) else return "Error: Cannot create new key" end - 将脚本加载到Redis:
SCRIPT LOAD "<上述Lua脚本内容>",获取返回的脚本SHA1值 - 后续调用时使用
EVALSHA <SHA1值> 1 <键名> <值> [其他SET参数]执行
注意:该方法需应用端配合调用自定义脚本,若无法修改应用代码则无法使用。
额外提示
- 所有配置修改后,记得用
CONFIG REWRITE(针对内存和驱逐策略)或ACL SAVE(针对ACL)保存到配置文件,避免Redis重启后配置丢失。 - 第一种方法的内存值建议在业务低峰期设置,避免因内存波动立即触发OOM拦截。
内容的提问来源于stack exchange,提问作者CpnAhab
相关产品推荐
相关产品推荐

