对于大量密钥,scan()优于scan(),因为它为您提供了可以使用的迭代器,而不是尝试将所有密钥加载到内存中。
我的redis中有一个1B记录,而且我永远都无法获得足够的内存来一次返回所有密钥。
一对一扫描键
这是一个使用scan()的python代码段,以从商店中获取与某个模式匹配的所有键,并一一删除它们:
import redis
r = redis.StrictRedis(host='localhost', port=6379, db=0)
for key in r.scan_iter("user:*"):
# delete the key
r.delete(key)
批量扫描
如果要扫描的键列表非常大(例如,大于100k的键),则分批扫描它们将更加高效,如下所示:
import redis
from itertools import izip_longest
r = redis.StrictRedis(host='localhost', port=6379, db=0)
# iterate a list in batches of size n
def batcher(iterable, n):
args = [iter(iterable)] * n
return izip_longest(*args)
# in batches of 500 delete keys matching user:*
for keybatch in batcher(r.scan_iter('user:*'),500):
r.delete(*keybatch)
我对该脚本进行了基准测试,发现使用500个批处理的规模比一对一扫描密钥快5倍。 500批大小似乎是在Macbook Pro上本地运行的最佳选择,它在网络上可能有所不同。 我测试了10、100、500、1000和10000的批量大小。如果您想了解如何对它进行基准测试,请与我联系。
请注意,无论您使用scan()还是keys()方法,该操作都不是原子的,并且可能会部分失败。
绝对避免在命令行上使用XAGS
我不建议在其他地方重复此示例。 它不适用于unicode密钥,并且即使中等数量的密钥也非常慢:
redis-cli --raw keys "user:*"| xargs redis-cli del
在此示例中,xargs为每个密钥创建一个新的redis-cli进程! ike。
我对这种方法进行了基准测试,它比第一个python示例慢4倍,在该示例中,它逐个删除每个键,并且比500个批次中的删除慢20倍。