我编写了一个脚本来比较 redis 库中方法之间的查询速度。
据我了解,我不应该使用 redis.keys() 因为它是一个阻塞函数。首选方法是 scan_iter(),它不会阻塞。这就说得通了。但我不明白为什么 scan_iter 这么慢。
该脚本使用三种技术来查询 Redis 数据库。
选项 1 是迄今为止最快的。选项 2 的速度要慢 20 到 30 倍。选项 3 平均慢 4 倍。
为什么是这样?我的代码写错了吗?难道是我方法不对?redis.keys() 方法实际上是最佳选择吗?
from datetime import datetime
from time import sleep
import redis
r = redis.StrictRedis(host='192.168.3.16', port=6379, decode_responses=True, db= 0)
def query_keys():
start = datetime.now()
redis_keys = r.keys(pattern='*')
redis_keys = [x for x in redis_keys if not x.startswith('1_')]
values = r.mget(redis_keys)
end = datetime.now()
print(str(len(values)) + ' values queried in ' + str(end - start) + ' with keys and mget.')
def query_scaniter():
start = datetime.now()
values = []
for s in r.scan_iter():
if not s.startswith('1_'):
values.append(r.get(s))
end = datetime.now()
print(str(len(values)) + ' values queried in ' + str(end - start) + ' with scan_iter.')
def query_scaniter_mget():
start = datetime.now()
redis_keys = []
for s in r.scan_iter():
if not s.startswith('1_'):
redis_keys.append(s)
values = r.mget(redis_keys)
end = datetime.now()
print(str(len(values)) + ' values queried in ' + str(end - start) + ' with scan_iter and mget.')
for i in range(3):
query_keys()
query_scaniter()
query_scaniter_mget()
print('\n')
sleep(5)
Output:
3532 values queried in 0:00:00.046872 with keys and mget.
3532 values queried in 0:00:00.781314 with scan_iter.
3532 values queried in 0:00:00.109385 with scan_iter and mget.
3526 values queried in 0:00:00.031245 with keys and mget.
3522 values queried in 0:00:00.812616 with scan_iter.
3522 values queried in 0:00:00.125007 with scan_iter and mget.
3529 values queried in 0:00:00.031246 with keys and mget.
3531 values queried in 0:00:00.797011 with scan_iter.
3530 values queried in 0:00:00.109357 with scan_iter and mget.
Run Code Online (Sandbox Code Playgroud)
这些结果符合预期。
避免的原因KEYS不是它速度慢,而是它会阻塞服务器,阻止它满足其他客户端请求。相比之下,SCAN一次仅返回一些结果,从而允许服务器保持对所有客户端的响应。
代价是进行大量SCAN调用会带来额外的开销(包括所有这些往返的网络开销)。所以你的客户端的总时间会更长,但你不会削弱服务器,这通常是一个更重要的考虑因素。
MGET请注意,如果您有大量密钥,您可能会遇到同样的问题。最可扩展的解决方案(与最快的不同)是使用 一次获取几个密钥SCAN,然后获取MGET这些密钥。
| 归档时间: |
|
| 查看次数: |
11581 次 |
| 最近记录: |