redis批量删除key

最近生产环境的redis服务器由于key过期不及时,现在发现时key的个数已经暴增到5000多万了。然后运维同学那边就报警了,最大内存12G,已经用了9G多了,正好下面快要双11了,让我们快些解决。

redis服务器里面堆积大量的队列状态相关的key,其实这些key可以设置有效期,或者任务完成以后删除或者过期,但是由于我们使用类库的问题,这些key既没有删除也没有过期,堆积到redis里面去了,现在我们要做的就是删除这些无用key。在删除这些keys的过程中,走了不少弯路,这里说一下我最终采用的方案。

redis的del函数可以删除单个key,也可以删除多个key,del函数官方文档可以看这里。在google之后看到目前网络上很多文章的思路是使用keys匹配返回要删除的key,然后调用del函数去删除。这种方案在数据量较小时无可厚非,但如果像我这样面临的处理的数据有5千W时,keys的阻塞问题可能会给线上生产环境带来致命的问题。所以我们需要对这种方案作出一些修改。

可喜的是自从2.8.0以后redis提供scan来遍历key,而且这个过程是非阻塞,不会影响线上生产环境。最终经过修改的方案是用scan遍历要删除的key,然后调用del删除。

下面是我用python写的用来删除key的脚本。

import sys,redis

r = redis.Redis(host="127.0.0.1", port=6379,db=0)

if  len(sys.argv) <= 1:
    print("必须指明匹配key字符串")
    exit(1)
pattern = sys.argv[1]

cursor = 0
num = 1
while 1 :
    resut = r.scan(cursor, pattern, 10000)
    del_keys = []
    for i in resut[1]:
        key = i.decode()
        del_keys.append(key)
    #print("del keys len :%d" % len(result))
    if len(del_keys) == 0:
        break
    r.delete(*del_keys)
    cursor = resut[0]
    print("delete keys num : %dw" % (num))
    num +=1

print("done\n")

如何利用我这个脚本删除符合某个规则的key哪,如以king开头的key?

下面的命令即可完成上面的问题。

python3 main.py "king*"

期间我看到网上利用keys+del的lua脚本的方案,花了一段时间把scan+del改成lua脚本来删除。但是可惜的是目前redis并不支持这么做,由于scan返回的结果是不确定的,所以禁止在其后直接调用del操作。

标签:Redis 发布于:2019-11-04 21:19:18