Redis 批量删除键
1. 简介
在Redis中批量优雅的删除大量键是一个很麻烦的问题,下面例举常用的方法和优缺点。
2. keys+del命令
使用keys
使用查找所有匹配的键,然后在使用del
一起批量删除。
优点
- 操作简单。
缺点
- 查找性能特别差,需要遍历所有键。如果redis key特别多,还有可能造成redis短时间无法提供服务。
- 网络性能占用多,所有匹配键都需要发送到
redis客户端
,如果匹配键特别多会占用大量网络带宽(这个问题可以通过Lua脚本来解决)。 - 占用内存多,需要大量内存暂存已经找到的键。
import redis
r = redis.Redis(host='127.0.0.1', port=6379, db=0)
# 查找
keys = r.keys("example-*")
# 删除
r.delete(*keys)
3. SCAN命令
- 使用SCAN命令迭代匹配特定模式的键。
- 对于每次SCAN迭代返回的键,使用DEL命令进行删除。
- 重复上述步骤,直到SCAN命令返回的游标为0,表示迭代完成。
优点
- 非阻塞,不会影响Redis服务器的其他操作。
- 可以控制每次迭代的键数量,减少内存占用。
缺点
- 在高并发场景下,很难保证所有匹配的键都完全删除,需要多次迭代。
import redis
r = redis.Redis(host='127.0.0.1', port=6379, db=0)
cursor = 0 # 以0开始
while True:
cursor, keys = r.scan(cursor=cursor, match='example-*', count=100)
if cursor == 0: # 以0结束
break
if keys:
r.delete(*keys)
4. UNLINK命令
UNLINK命令是Redis提供的一个异步删除命令,与DEL命令不同,UNLINK命令会立即返回,而删除操作将在后台异步进行。
- 使用SCAN命令或KEYS命令获取要删除的键列表。
- 使用UNLINK命令代替DEL命令进行删除。
优点
- 异步删除,不会阻塞Redis服务器。
缺点
- 删除的完成时间不可预测。
- 在某些情况下可能需要额外的逻辑,保证在需要删除的键已经删除。
import redis
r = redis.Redis(host='127.0.0.1', port=6379, db=0)
cursor = 0 # 以0开始
while True:
cursor, keys = r.scan(cursor=cursor, match='example-*', count=100)
if cursor == 0: # 以0结束
break
if keys:
r.unlink(*keys)
5. Lua脚本
上面所有的示例都可以转换成Lua脚本版本,下面只演示其中一个。
优点
- 大量降低
redis客户端
与redis服务器
的RTT时间。 - 大量节约了
redis服务器
的带宽。
缺点
- 提高操作的复杂。
import redis
r = redis.Redis(host='127.0.0.1', port=6379, db=0)
lua_script = """
local key1 = KEYS[1]
local delete_count = 0
local delete_keys = redis.call('keys', key1)
if #delete_keys > 0 then
delete_count = redis.call('del',unpack(delete_keys))
end
return delete_count
"""
# 注册脚本
script = r.register_script(lua_script)
# 执行
result = script(keys=['example-*'])
print(result)
6. 总结
- 尽量避免在生产环境使用
keys
:使用keys
不可避免的会出现性能问题。 - 分批次删除:不要一次删除防止
redis服务端
处理大量键进入阻塞状态。