一尘不染

快速迭代Redis DB中所有键和值的方法

redis

我有大约350,000个密钥的数据库。目前,我的代码只是循环遍历所有键,并从db获取其值。

但是,这花费了将近2分钟的时间,这似乎确实很慢,达到redis-benchmark了10万次请求/ 3秒。

我已经研究过流水线技术,但是我需要返回每个值,以便最终得到键值对的字典。

目前,我正在考虑在代码中使用线程来加快速度,这是处理此用例的最佳方法吗?

这是我到目前为止的代码。

import redis, timeit
start_time = timeit.default_timer()
count = redis.Redis(host='127.0.0.1', port=6379, db=9)
keys = count.keys()

data = {}

for key in keys:
    value = count.get(key)
    if value:
        data[key.decode('utf-8')] = int(value.decode('utf-8'))

elapsed = timeit.default_timer() - start_time

print('Time to read {} records: '.format(len(keys)), elapsed)

阅读 281

收藏
2020-06-20

共1个答案

一尘不染

首先,最快的方法是在EVAL中完成所有这些操作。

接下来,推荐的迭代所有密钥的方法是SCAN。它的迭代速度不会比快KEYS,但是将允许Redis在其之间处理一些其他操作,因此将有助于整体应用程序行为。

该脚本将类似于local data={} local i=1 local mykeys=redis.call(\"KEYS\",\"*\") for k=1,#mykeys do local tmpkey=mykeys[k] data[i]={tmpkey,redis.call(\"GET\",tmpkey)} i=i+1 end return data,但是如果您具有GET无法访问的键(如集,列表),它将失败。您需要为其添加错误处理。如果需要排序,则可以直接在LUA中进行,也可以稍后在客户端进行。第二个会比较慢,但是不会让其他Redis实例用户等待。

样本输出:

127.0.0.1:6370> eval "local data={} local i=1 local mykeys=redis.call(\"KEYS\",\"*\") for k=1,#mykeys do local tmpkey=mykeys[k] data[i]={tmpkey,redis.call(\"GET\",tmpkey)} i=i+1 end return data" 0
1) 1) "a"
   2) "aval"
2) 1) "b"
   2) "bval"
3) 1) "c"
   2) "cval"
4) 1) "d"
   2) "dval"
5) 1) "e"
   2) "eval"
6) 1) "f"
   2) "fval"
7) 1) "g"
   2) "gval"
8) 1) "h"
   2) "hval"
2020-06-20