当前位置:首页 > 问答 > 正文

Redis模糊查找怎么快点拿到想要的值,实操分享和思路探讨

今天咱们来聊聊Redis模糊查找怎么能更快点儿,这事儿其实挺常见的,比如你用Redis存了很多用户会话,key可能是 user:session:12345user:session:67890 这种,现在你想找出所有以 user:session:aaa 开头的key,或者找出key里包含 temp 的所有数据,这时候就得用上模糊查找了。

Redis自己提供了几个命令来做模糊查找,最常用的就是 KEYSSCAN

先说那个“坑爹”的 KEYS 命令

(来源:Redis官方文档对KEYS命令的警告性说明) 你一上来可能会用 KEYS user:session:aaa* 这个命令,它确实简单直接,你一下令,Redis立马给你把匹配的key全列出来,但为啥说它坑爹呢?因为Redis是单线程的,它执行命令的时候别的命令都得等着,如果你的Redis里存了几百万甚至上千万个key,你用 KEYS 命令去扫,这个过程可能会卡住Redis好几秒甚至更久,这段时间内Redis就跟“死”了一样,什么读写操作都处理不了,生产环境上用这个命令简直就是灾难,几乎所有的Redis老手都会告诉你:绝对不要在线上环境用 KEYS 命令

那怎么办?用 SCAN 命令迭代着来

(来源:Redis官方文档推荐的遍历键空间的方法) SCAN 命令就是来救场的,它不像 KEYS 那样一次性把所有结果都给你,而是像翻书一样,一页一页地翻,你第一次执行 SCAN 0 MATCH user:session:aaa*,它会返回两部分内容:一个是下一次扫描需要的“游标”(比如返回了 65),还有一个是当前这一页找到的几个key。

然后你再用 SCAN 65 MATCH user:session:aaa* 继续扫,就这样一遍一遍直到游标变回 0,说明全部扫完了,这个过程的好处是,每次操作都只耗费一点点时间,不会长时间阻塞Redis,对线上服务的影响微乎其微,你可以写个小脚本或者在你的程序里用一个循环来跑 SCAN

光找到key还不够,怎么快点拿到值?

SCAN 找到了所有符合条件的key,这只是第一步,你最终要的是这些key对应的value,最笨的办法是,在程序里拿到key的列表,然后一个个去执行 GET 或者 HGETALL 之类的命令,如果key有几千个,那就要发起几千次网络请求,这速度肯定快不了,网络开销太大了。

(来源:基于Redis管道化技术提升批量操作效率的常见优化实践) 这里有个提速的实操技巧:使用管道(pipeline),你可以把管道理解成一个批处理工具,平常你发一个命令,要等Redis回复了再发下一个,用了管道,你可以一口气把几十个甚至几百个 GET 命令打包,一次性发给Redis,然后Redis也一次性把所有的结果打包还给你,这样就大大减少了网络来回的次数,速度能提升非常多,在Python的redis-py库、Java的Jedis等客户端里,都很容易实现管道操作。

换个思路:从设计上避免模糊查找

(来源:常见的Redis键设计模式与优化经验) 上面说的都是在“事后”怎么找得快,但更高明的办法是,在存数据的时候,就提前想好以后可能要怎么查,从根儿上避免大规模模糊查找

  1. 使用合适的数据结构:比如你不是要找所有包含 temp 的key吗?那你在存这些临时key的时候,可以同时把它们塞到一个Set集合里,给这个集合起个名叫 all_temp_keys,以后你想找所有临时key,直接 SMEMBERS all_temp_keys 就行了,又快又准,根本不用模糊扫描。

  2. 利用哈希(Hash)结构:比如你有一堆用户配置项,本来你可能设计成 user:config:1001, user:config:1002... 这样的key,如果你想批量查一批用户的配置,就得模糊找key,不如换种方式,用一个大的Hash结构,key就叫 users:config,里面的field是用户ID(1001, 1002),value是具体的配置JSON,这样你想查哪几个用户的配置,直接用 HMGET users:config 1001 1002 1003 一条命令就全拿到了,效率极高。

  3. 有序集合(Sorted Set)按分数范围查:如果你的数据有某种顺序(比如按时间戳),可以存到有序集合里,用分数代表时间,这样你要查某个时间段的数据,直接用 ZRANGEBYSCORE 按分数范围查询,这比模糊匹配key要精确和快速得多。

总结一下

  • 紧急情况、数据量小:在测试环境或者确定没风险时,可以用 KEYS 看一眼,但心里要清楚后果。
  • 线上环境、常规操作:老老实实用 SCAN 命令分批遍历,避免服务阻塞。
  • 拿到key后取value:一定要用管道(pipeline)批量操作,减少网络开销。
  • 长远之计、最优方案:在设计数据存储结构时多动脑筋,通过使用集合、哈希等结构维护索引,或者选择支持按范围查询的数据结构,从根本上让模糊查找变得不再必要,这才是让Redis飞起来的关键。

Redis模糊查找怎么快点拿到想要的值,实操分享和思路探讨