你手头有一份黑名单,是几万个电话号,你的系统需要提供一个功能,给你若干个电话号,比如10个,你需要判断这10个电话号哪些处于黑名单中。
考虑将这些电话号都存入到一个集合中,redis的集合支持判断一个key是否在集合中,但场景要求支持批量查询,这个时候就不要考虑一个电话查询一次了,时间都浪费在了网络IO上,是非常不划算的,必须找到一种方法,一次性的将这10个电话发送到redis进行判断。
可以将这10个电话写入到一个新的集合中,然后用这个新集合与黑名单集合做交集,交集里的内容正是所需要的结果,这个过程需要三个步骤来完成
import time
from random import sample
from redis.client import Redis
r = Redis(host='127.0.0.1', port=6379, db=0, password='密码')
def create_data_for_set():
for i in range(10000, 50001):
r.sadd('black_set', i)
def test_set_ex(count):
lst = sample(range(10000, 50001), count)
t1 = time.time()
for i in range(10):
r.sadd('black_set_2', *lst) # 将数据存入一个新的集合
res = r.sinter(['black_set', 'black_set_2'])
r.delete('black_set_2') # 删除临时集合
t2 = time.time()
print(f'批量查询{count}个key耗时: ' + str((t2 - t1) / 10))
def test_set():
test_set_ex(5)
test_set_ex(10)
test_set_ex(50)
test_set_ex(100)
test_set_ex(200)
test_set_ex(300)
test_set_ex(400)
test_set_ex(500)
test_set_ex(600)
test_set_ex(700)
test_set_ex(800)
test_set_ex(900)
test_set_ex(1000)
test_set_ex(1500)
test_set_ex(2000)
先执行函数create_data_for_set ,准备好数据,向集合中写入5万个key, 执行test_set函数,测试不同数量的批量查询对性能的影响,得到结果如下
批量查询5个key耗时: 0.01289970874786377
批量查询10个key耗时: 0.00995328426361084
批量查询50个key耗时: 0.010499835014343262
批量查询100个key耗时: 0.012500858306884766
批量查询200个key耗时: 0.013652372360229491
批量查询300个key耗时: 0.01479964256286621
批量查询400个key耗时: 0.016852569580078126
批量查询500个key耗时: 0.0216951847076416
批量查询600个key耗时: 0.02585453987121582
批量查询700个key耗时: 0.028419804573059083
批量查询800个key耗时: 0.026099658012390135
批量查询900个key耗时: 0.0303267240524292
批量查询1000个key耗时: 0.027204418182373048
批量查询1500个key耗时: 0.03538084030151367
批量查询2000个key耗时: 0.04379713535308838
一个电话号用一个key来存储,批量查询时,用mget批量操作
def create_data_for_mget():
for i in range(10000, 50001):
key = f'black::{i}'
r.set(key, 1)
def test_mget_ex(count):
lst = sample(range(10000, 50001), count)
t1 = time.time()
for i in range(10):
res = r.mget([f'black::{item}' for item in lst])
t2 = time.time()
print(f'批量查询{count}个key耗时: ' + str((t2-t1)/10))
def test_mget():
test_mget_ex(5)
test_mget_ex(10)
test_mget_ex(50)
test_mget_ex(100)
test_mget_ex(200)
test_mget_ex(300)
test_mget_ex(400)
test_mget_ex(500)
test_mget_ex(600)
test_mget_ex(700)
test_mget_ex(800)
test_mget_ex(900)
test_mget_ex(1000)
test_mget_ex(1500)
test_mget_ex(2000)
test_mget()
得到的结果
批量查询5个key耗时: 0.006318092346191406
批量查询10个key耗时: 0.0033003568649291994
批量查询50个key耗时: 0.004325366020202637
批量查询100个key耗时: 0.004499959945678711
批量查询200个key耗时: 0.0066995382308959964
批量查询300个key耗时: 0.00950002670288086
批量查询400个key耗时: 0.011799359321594238
批量查询500个key耗时: 0.011200904846191406
批量查询600个key耗时: 0.013999748229980468
批量查询700个key耗时: 0.014699149131774902
批量查询800个key耗时: 0.01600046157836914
批量查询900个key耗时: 0.02149970531463623
批量查询1000个key耗时: 0.02039961814880371
批量查询1500个key耗时: 0.030499577522277832
批量查询2000个key耗时: 0.03730003833770752
拥电话号做hash的field,批量查询时使用hmget方法
def create_data_for_hmget():
for i in range(10000, 50001):
key = f'black'
r.hset(key, f'black::{i}', 1)
def test_hmget_ex(count):
lst = sample(range(10000, 50001), count)
t1 = time.time()
for i in range(10):
res = r.hmget('black', [f'black::{item}' for item in lst])
t2 = time.time()
print(f'批量查询{count}个key耗时: ' + str((t2-t1)/10))
def test_hmget():
test_hmget_ex(5)
test_hmget_ex(10)
test_hmget_ex(50)
test_hmget_ex(100)
test_hmget_ex(200)
test_hmget_ex(300)
test_hmget_ex(400)
test_hmget_ex(500)
test_hmget_ex(600)
test_hmget_ex(700)
test_hmget_ex(800)
test_hmget_ex(900)
test_hmget_ex(1000)
test_hmget_ex(1500)
test_hmget_ex(2000)
test_hmget()
得到结果如下
批量查询5个key耗时: 0.005600094795227051
批量查询10个key耗时: 0.0027003049850463866
批量查询50个key耗时: 0.003399515151977539
批量查询100个key耗时: 0.0038997173309326173
批量查询200个key耗时: 0.005700159072875977
批量查询300个key耗时: 0.007200384140014648
批量查询400个key耗时: 0.008800601959228516
批量查询500个key耗时: 0.010499835014343262
批量查询600个key耗时: 0.012400221824645997
批量查询700个key耗时: 0.013699531555175781
批量查询800个key耗时: 0.01600005626678467
批量查询900个key耗时: 0.016799330711364746
批量查询1000个key耗时: 0.01909959316253662
批量查询1500个key耗时: 0.02709958553314209
批量查询2000个key耗时: 0.03717978000640869
对比3种方法的响应时间,string和hash近乎相同,略高于使用集合的方案。我个人更喜欢使用hash,相比于string,可以避免生成大量的key。
QQ交流群: 211426309