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

Redis里怎么快速查数据有没有值,简单又实用的方法分享

在Redis里,怎么才能又快又简单地检查一个数据到底存不存在?别整那些复杂的概念,就聊最直接、最常用的方法。

你得知道Redis最基本的一个操作,就是EXISTS命令,这个方法可以说是最简单直接的了,你用不着管这个键对应的值是什么,是字符串还是列表,你只关心它有没有,这时候,EXISTS命令就派上用场了,根据Redis官方文档(来源:Redis命令文档)的说明,你只需要把你想查的那个键(key)的名字跟在EXISTS后面就行了,你有个键叫 user:1001:name,你想知道Redis里有没有存着这个东西,你就输入命令 EXISTS user:1001:name,Redis会给你返回一个数字,如果是1,那就表示这个键存在;如果是0,那就表示没找到,不存在,这个方法的好处是啥呢?就是直白,你问什么,它就直接回答是还是否,速度非常快,因为Redis直接在它内存里的哈希表里查一下就行了,几乎是瞬间完成,这应该是你首先想到的方法。

有时候情况会稍微复杂一点点,比如说,你不是查一个键,而是想一口气查好几个键,看看它们是不是都存在,你可能会想,那我写个循环,一个一个地用EXISTS命令去查呗,这样当然可以,但不是最快的办法,因为每个命令都要从你的客户端发到Redis服务器,服务器再处理再返回,这个来回通信的时间(网络延迟)如果多了,就会慢,那有没有更高效的办法呢?有的,Redis的EXISTS命令很贴心,它支持一次查多个键,你可以直接把好几个键的名字都跟在命令后面,像这样:EXISTS key1 key2 key3,然后Redis会返回一个数字,这个数字不是告诉你每个键的情况,而是告诉你传入的这些键里面,有几个是存在的,比如你查三个键,返回2,就表示有三个键里有两个是存在的,如果你需要知道具体是哪几个存在,这个方法就不够了,但如果你只是想知道这一批键里是不是都存在,或者存在几个,这个方法就非常高效,一次网络通信就全搞定了。

Redis里怎么快速查数据有没有值,简单又实用的方法分享

咱们再往深里想一层,有时候啊,我们检查一个键是否存在,并不是最终目的,我们的真实目的可能是:如果存在,我就把它拿出来用;如果不存在,我可能要去数据库查一下,然后塞到Redis里,方便下次用,这是一个非常非常常见的缓存使用模式,叫做“缓存查询”,如果你按照刚才的思路,先EXISTS一下,如果存在,再发一个GET命令去取数据,这就有个问题:你发了两次命令,跑了两次网络通信,在需要高性能的场景下,这两次通信的延迟加起来,可能就有点慢了。

那有没有办法合二为一呢?答案是肯定的,这里就要提到另一个非常实用的命令了,叫GET命令本身,没错,就是那个用来取值的GET命令,根据Redis的设计(来源:Redis数据类型文档),当你对一个不存在的键使用GET命令时,它不会报错,而是会返回一个特殊的值 nil,这个特性可以被我们巧妙地利用起来,你的操作可以变成这样:直接尝试用GET命令去拿这个键的值,如果返回的不是nil,太好了,数据直接到手,一步完成,如果返回的是nil,那就说明键不存在,这时候你再去数据库查询,然后用SET命令把数据设置到Redis里,你看,这样就把检查存在和获取值两个步骤,在一次通信中完成了,这种方法比先EXISTSGET要更高效,因为它减少了网络往返的次数,这种方法有个小前提,就是你确实需要这个键的值,如果你仅仅是做存在性检查,完全不需要它的值,那还是用EXISTS更纯粹。

Redis里怎么快速查数据有没有值,简单又实用的方法分享

除了这些基本方法,还有一种数据结构能帮上忙,叫做布隆过滤器(Bloom Filter),不过这个东西稍微高级一点点,但因为它对于解决“是否存在”这个问题特别高效,所以也值得简单提一下,布隆过滤器的特点是,它能告诉你一个东西“肯定不存在”或者“可能存在”,注意这个“可能存在”,它有一点点误判的概率,但好处是速度极快,而且非常节省内存,根据布隆过滤器的原理介绍(来源:计算机科学常用算法),它特别适合用在那种数据量非常大,而且绝大多数情况下数据都不存在的场景,检查一个用户名是否已经被注册了,通常大部分输入的用户名都是没被注册的,布隆过滤器能瞬间告诉你“肯定不存在”,你就可以放心注册了,对于那些它说“可能存在”的,你再去数据库做一次精确查询确认一下,在Redis里,你可以通过RedisBloom这个模块来使用布隆过滤器,虽然需要额外安装模块,但在特定的大数据量排查场景下,它的速度优势是前面几种方法无法比拟的。

所以总结一下,在Redis里快速查数据有没有值:

  1. 最简单直接:用 EXISTS 命令,适合只关心是否存在,不关心具体值的场景,查多个键可以一次完成。
  2. 最常见实用:直接使用 GET 命令,通过判断返回值是否为 nil 来同时完成“检查”和“获取”两个动作,是缓存查询模式下的最佳实践。
  3. 应对海量数据:考虑使用布隆过滤器(如果Redis安装了相应模块),用极小的内存空间实现高效的存在性预判,适合允许有微小误判率的场景。

你就根据你实际的需求,从这几个方法里挑一个最合适的用就行,第二种方法,也就是直接GET,在构建缓存时是用得最多的,因为它最符合我们的实际操作逻辑。