使用python获取Redis数据库中的所有密钥

使用python获取Redis数据库中的所有密钥,python,database,redis,Python,Database,Redis,有一篇关于Redis命令获取所有可用密钥的帖子,但我想用Python来实现 有什么方法可以做到这一点吗?是的,从StrictRedis模块使用: >>> import redis >>> r = redis.StrictRedis(host=YOUR_HOST, port=YOUR_PORT, db=YOUR_DB) >>> r.keys() 提供空模式将获取所有模式。根据链接的页面: 键(模式=“*”) 返回匹配模式的键列表 使用Pyre

有一篇关于Redis命令获取所有可用密钥的帖子,但我想用Python来实现

有什么方法可以做到这一点吗?

是的,从StrictRedis模块使用:

>>> import redis
>>> r = redis.StrictRedis(host=YOUR_HOST, port=YOUR_PORT, db=YOUR_DB)
>>> r.keys()
提供空模式将获取所有模式。根据链接的页面:

键(模式=“*”)

返回匹配模式的键列表

使用Pyredis库

从2.8.0开始提供

时间复杂度:每个呼叫的时间复杂度为O(1)。O(N)表示完整的迭代,包括足够的命令调用,以使光标返回0。N是集合中的元素数。

使用
scan\u iter()

scan\u iter()
对于大量键优于
keys()
,因为它提供了一个迭代器,您可以使用它,而不是尝试将所有键加载到内存中

我的redis中有一个1B记录,我永远无法获得足够的内存一次返回所有的钥匙

逐个扫描按键

下面是一个python代码片段,它使用
scan\u iter()
从存储中获取与模式匹配的所有密钥,并逐个删除它们:

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倍。我测试了不同的批量(35050010005000),发现500的批量似乎是最佳的

请注意,无论您使用的是
scan\u iter()
还是
keys()
方法,该操作都不是原子操作,可能会部分失败

绝对避免在命令行上使用XARGS

我不推荐在其他地方重复的这个例子。对于unicode键,它将失败,对于中等数量的键,它的速度也非常慢:

redis-cli --raw keys "user:*"| xargs redis-cli del
在本例中,xargs为每个键创建一个新的redis cli进程!那太糟糕了


我对这种方法进行了基准测试,其速度比第一个python示例慢4倍,第一个python示例一个接一个地删除每个键,比批量删除500个键慢20倍。

我想添加一些示例代码,以配合Patrick的答案和其他答案。
这显示了使用键和扫描技术的结果。 请注意,Python3使用zip_longest而不是izip_longest。下面的代码循环遍历所有键并显示它们。我将batchsize作为变量设置为12,以使输出更小

我写这篇文章是为了更好地理解批处理键是如何工作的

import redis
from itertools import zip_longest

\# connection/building of my redisObj omitted here

\# iterate a list in batches of size n
def batcher(iterable, n):
    args = [iter(iterable)] * n
    return zip_longest(*args)
    
result1 = redisObj.get("TestEN")
print(result1)
result2 = redisObj.get("TestES")
print(result2)

print("\n\nLoop through all keys:")
keys = redisObj.keys('*')
counter = 0
print("len(keys)=", len(keys))
for key in keys:
    counter +=1
    print (counter, "key=" +key, " value=" + redisObj.get(key))

print("\n\nLoop through all keys in batches (using itertools)")
\# in batches of 500 delete keys matching user:*
counter = 0
batch_counter = 0
print("Try scan_iter:")
for keybatch in batcher(redisObj.scan_iter('*'), 12):
    batch_counter +=1
    print(batch_counter, "keybatch=", keybatch)
    for key in keybatch:
        if key != None:
            counter += 1
            print("  ", counter, "key=" + key, " value=" + redisObj.get(key))
示例输出:

Loop through all keys:
len(keys)= 2
1 key=TestES  value=Ola Mundo
2 key=TestEN  value=Hello World


Loop through all keys in batches (using itertools)
Try scan_iter:
1 keybatch= ('TestES', 'TestEN', None, None, None, None, None, None, None, None, None, None)
   1 key=TestES  value=Ola Mundo
   2 key=TestEN  value=Hello World

注意:redis comamnds是单线程的,因此执行keys()可以阻止其他redis活动。请参阅此处的精彩帖子,该帖子更详细地解释了这一点:

是对上述公认答案的补充

scan\u iter
可与
count
参数一起使用,以告知redis在一次迭代中搜索多个键。这可以显著加快密钥获取速度,特别是在与匹配模式一起使用以及在较大的密钥空间上使用时

使用非常高的计数值时要小心,因为这可能会破坏其他并发查询的性能


这里有一篇文章介绍了更多细节和一些基准测试。

请注意,不鼓励在生产服务器上使用此命令。如果您有大量的密钥,您的ReDIS实例在处理这个请求时不会对任何其他请求作出响应,这可能需要相当长的时间来完成。考虑添加一个引用“代码>扫描< /代码>命令,因为它现在是获得每个请求的O(1)时间复杂度的所有密钥的首选方式。(对于所有请求都是O(N)
r.keys()
在尝试匹配模式而不仅仅是返回所有键时速度非常慢。在回答中建议使用<代码>扫描<代码>below@KonstantineNikolaou我通知了OP,他很高兴地拒绝了我的回答而接受了另一个。感谢您的报道,我很久以前就使用过这个选项,但现在我没有把重点放在这个主题上,来检查什么是最好的。@SoroushParsa如果您支持
scan()
选项,那么请向上投票另一个答案。事实上,我的是被接受的一个,我要求OP接受另一个。对我来说,对这一条进行向下表决本身并不真正符合“这个答案没有用”的说法。当在r.SCAN_iter()上迭代时,我不断得到“redis.exceptions.ResponseError:unknown command'SCAN'”。知道为什么吗?我还没有找到anwswer。@BringBackCommodore64您的redis版本太旧,请安装一个新版本。@piokuc好吧,我还没有升级我的redis,但您的猜测显然是对的@LeiYang redis搜索允许全局/通配符。所以“我的钥匙*”,“用户”,“用户:”。izip_longest在Python 3中被重命名为zip_longest
Loop through all keys:
len(keys)= 2
1 key=TestES  value=Ola Mundo
2 key=TestEN  value=Hello World


Loop through all keys in batches (using itertools)
Try scan_iter:
1 keybatch= ('TestES', 'TestEN', None, None, None, None, None, None, None, None, None, None)
   1 key=TestES  value=Ola Mundo
   2 key=TestEN  value=Hello World