27人参与 • 2026-01-13 • Redis
在现代分布式系统中,redis作为高性能的内存数据库,承载着缓存、会话存储、消息队列等关键功能。随着业务的发展,数据库中往往会积累大量临时数据或过期的键值对。特别是那些包含特定时间戳或模式的键,如日志数据、临时会话、缓存数据等,需要定期清理以释放内存空间。
然而,错误的删除操作可能带来灾难性后果。误删生产数据、操作期间服务阻塞、内存溢出等问题时有发生。本文将深入探讨如何在redis中安全、高效地删除包含特定模式(如"202512")的所有键值对,涵盖从基础命令到高级技巧的全方位解决方案。
redis支持使用通配符进行键的模式匹配,主要通配符包括:
*:匹配任意数量的字符?:匹配单个字符[abc]:匹配括号内的任意一个字符[a-z]:匹配字符范围内的任意一个字符对于我们要删除的包含"202512"的键,模式*202512*表示:
在真实业务中,这种模式可能对应多种数据:
user:session:20251201、log:20251215:errorbatch:202512:processing、export:202512:resultproduct:cache:202512:categorytmp:upload:202512:filename基本用法:
-- 查找所有匹配的键 keys "*202512*" -- 手动或编程方式删除 del key1 key2 key3 ...
优点:
致命缺点:
适用场景:
# 一次性删除(生产环境慎用) redis-cli keys "*202512*" | xargs redis-cli del
这种方法的危险在于,如果keys命令执行时间过长,管道可能超时或中断,导致部分删除失败。
scan命令是keys的安全替代方案,具有以下特点:
基础scan用法:
-- 第一次迭代 scan 0 match "*202512*" count 100 -- 后续迭代(使用返回的新游标) scan "游标值" match "*202512*" count 100
完整的删除脚本:
# 使用scan逐步删除
cursor="0"
while [ "$cursor" != "0" ] || [ "$first" == "true" ]; do
if [ "$cursor" == "0" ]; then first="false"; fi
result=$(redis-cli scan $cursor match "*202512*" count 1000)
cursor=$(echo "$result" | head -1)
keys=$(echo "$result" | tail -n +2)
if [ -n "$keys" ]; then
echo "$keys" | tr ' ' '\n' | xargs -l 1000 redis-cli del
fi
done
为什么选择lua脚本?
推荐的lua脚本:
eval "
local pattern = '*202512*'
local batchsize = 1000
local deletedcount = 0
local cursor = '0'
repeat
-- 使用scan获取一批key
local scanresult = redis.call('scan', cursor, 'match', pattern, 'count', batchsize)
cursor = scanresult[1]
local keys = scanresult[2]
-- 如果找到key,批量删除
if #keys > 0 then
redis.call('del', unpack(keys))
deletedcount = deletedcount + #keys
-- 可选:添加延迟,减少对主线程的影响
-- if #keys >= batchsize then
-- redis.call('debug', 'sleep', '0.001')
-- end
end
-- 如果游标回到0,表示迭代完成
until cursor == '0'
return {
totaldeleted = deletedcount,
status = 'completed'
}
" 0
脚本优化技巧:
batchsize(通常500-5000)内存优化:
-- 在删除前检查内存使用 info memory -- 删除后手动触发内存整理(redis 4.0+) memory purge
连接优化:
# 使用pipeline提高效率
redis-cli --scan --pattern "*202512*" | awk '{print "del "$0}' | redis-cli --pipe
删除前的检查清单:
监控命令示例:
-- 监控删除过程中的内存变化 monitor -- 查看删除进度 info stats
健壮的lua脚本(带错误处理):
eval "
local function safedelete(pattern)
local maxattempts = 3
local attempt = 1
local cursor = '0'
local totaldeleted = 0
while attempt <= maxattempts do
local success, errormsg = pcall(function()
repeat
local result = redis.call('scan', cursor, 'match', pattern, 'count', 1000)
cursor = result[1]
local keys = result[2]
if #keys > 0 then
redis.call('del', unpack(keys))
totaldeleted = totaldeleted + #keys
end
until cursor == '0'
end)
if success then
break
else
-- 记录错误,等待后重试
redis.log(redis.log_warning, 'attempt ' .. attempt .. ' failed: ' .. errormsg)
attempt = attempt + 1
if attempt <= maxattempts then
redis.call('debug', 'sleep', '0.5')
end
end
end
return totaldeleted
end
return safedelete('*202512*')
" 0
# 直接简单的方案 redis-cli keys "*202512*" | xargs -n 1000 redis-cli del
# 带详细日志的方案
redis-cli --scan --pattern "*202512*" --count 1000 | \
while read key; do
echo "deleting: $key"
redis-cli del "$key"
done
方案一:分时段处理
#!/bin/bash
# 分时段删除脚本
max_keys_per_batch=1000
sleep_time=1
total_deleted=0
cursor=0
while true; do
result=$(redis-cli scan $cursor match "*202512*" count $max_keys_per_batch)
cursor=$(echo $result | cut -d' ' -f1)
keys=$(echo $result | cut -d' ' -f2-)
if [ -n "$keys" ]; then
count=$(echo $keys | wc -w)
redis-cli del $keys
total_deleted=$((total_deleted + count))
echo "$(date): deleted $count keys, total: $total_deleted"
fi
if [ "$cursor" -eq "0" ]; then
break
fi
sleep $sleep_time
done
方案二:使用redis模块
对于redis 4.0+,可以考虑使用redisgears或自己编写模块实现更复杂逻辑。
| 方法 | 10万键耗时 | 内存影响 | 阻塞风险 | 推荐指数 |
|---|---|---|---|---|
| keys+del | 2-3秒 | 高 | 极高 | ★☆☆☆☆ |
| scan脚本 | 8-10秒 | 低 | 低 | ★★★★☆ |
| lua脚本 | 5-7秒 | 中 | 中 | ★★★★★ |
| pipeline | 4-6秒 | 中 | 中 | ★★★★☆ |
# 1. 准备测试数据
for i in {1..100000}; do
redis-cli set "test:202512:key$i" "value$i"
done
# 2. 测试各种方法
time redis-cli eval "...lua脚本..." 0
# 3. 监控性能指标
redis-cli info stats | grep -e "(keyspace_hits|keyspace_misses|expired_keys|evicted_keys)"
-- 先使用ttl检查是否为临时数据
eval "
local pattern = '*202512*'
local cursor = '0'
local permanentkeys = {}
repeat
local result = redis.call('scan', cursor, 'match', pattern, 'count', 100)
cursor = result[1]
local keys = result[2]
for _, key in ipairs(keys) do
local ttl = redis.call('ttl', key)
if ttl == -1 then -- 永久数据
table.insert(permanentkeys, key)
end
end
until cursor == '0'
return permanentkeys
" 0
对于redis cluster,需要每个节点单独处理:
# 获取所有节点
redis-cli cluster nodes | grep master | awk '{print $2}' | cut -d: -f1 | \
while read node; do
redis-cli -h $node --scan --pattern "*202512*" | xargs -l 1000 redis-cli -h $node del
done
# python自动化脚本示例
import redis
import logging
from datetime import datetime
class rediskeycleaner:
def __init__(self, host='localhost', port=6379):
self.redis = redis.redis(host=host, port=port)
self.logger = logging.getlogger(__name__)
def safe_delete_by_pattern(self, pattern, batch_size=1000, max_keys=none):
"""安全删除指定模式的key"""
deleted_count = 0
cursor = '0'
self.logger.info(f"starting deletion for pattern: {pattern}")
while true:
cursor, keys = self.redis.scan(
cursor=cursor,
match=pattern,
count=batch_size
)
if keys:
# 分批删除
for i in range(0, len(keys), 100):
batch = keys[i:i+100]
self.redis.delete(*batch)
deleted_count += len(batch)
self.logger.info(f"deleted {len(batch)} keys, total: {deleted_count}")
# 检查是否达到上限
if max_keys and deleted_count >= max_keys:
self.logger.info(f"reached max limit: {max_keys}")
return deleted_count
if cursor == 0:
break
self.logger.info(f"deletion completed. total deleted: {deleted_count}")
return deleted_count
# 使用示例
cleaner = rediskeycleaner()
cleaner.safe_delete_by_pattern("*202512*", batch_size=500)
# prometheus监控配置示例
rules:
- alert: redismassdeletion
expr: rate(redis_command_duration_seconds_sum{command="del"}[5m]) > 100
for: 2m
labels:
severity: warning
annotations:
summary: "大量删除操作进行中"
description: "redis del命令执行频率异常升高"
删除redis中包含特定模式的键值对是一个看似简单但实则充满风险的操作。总结本文内容,我们建议:
keys * 命令记住:在redis中,删除操作是不可逆的。谨慎的态度、充分的测试和恰当的工具选择,是确保操作成功的关键。
最后给出一个终极安全建议:在执行任何删除操作前,先执行一个重命名操作作为"软删除":
-- 先重命名,观察业务影响 rename old_key deleted:old_key -- 确认无误后再真正删除 del deleted:old_key
通过本文介绍的多种方法和最佳实践,你应该能够安全、高效地管理redis中的键值对清理工作,确保系统的稳定性和性能。
以上就是redis安全高效删除包含特定模式的所有键值对的完整方案的详细内容,更多关于redis删除包含特定模式的键值对的资料请关注代码网其它相关文章!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论