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

用Redis做检索工具类库,速度快还挺靠谱的那种感觉

说到用Redis做检索,很多人第一反应是:“Redis不是个缓存吗?怎么能当搜索来用?” 这话对,但也不全对,把它当成像Elasticsearch那样的专业全文搜索引擎,那肯定是走错了路,但如果你想要的是那种“速度飞快、实现简单、对付几百万数据量绰绰有余”的轻量级检索方案,Redis还真能给你一种“又快又靠谱”的惊喜感,这种感觉,有点像你本来只想找把水果刀切个苹果,结果发现手边这把瑞士军刀异常锋利,顺手就把其他小活儿也给干了。

这种能力的核心,来自于Redis丰富的数据结构,它不是靠一种数据结构打天下,而是让你像搭乐高一样,根据不同的检索需求,组合出最合适的方案。

第一种感觉:精准匹配的“闪电侠”。 这其实就是Redis最基础、最拿手的键值对查询,你有一个商品,商品ID是product:123,那么直接GET product:123,速度是微秒级的,快得没话说,但这种检索太“死板”了,你必须精确地知道键名,为了解决这个问题,我们可以请出集合这个帮手,给所有“上架中”的商品建一个集合,键叫products:active,里面存放所有活跃商品的ID,当你想获取所有上架商品时,先用SMEMBERS products:active拿到所有ID,然后再用这些ID去批量获取商品的详细信息,这种“集合筛选项 + 主键查询”的模式,是实现多条件精准筛选的基础,你还可以有category:electronics(电子产品类目集合)、brand:apple(苹果品牌集合),要查“上架中的苹果电子产品”,只需要用SINTER命令求这几个集合的交集,瞬间就能得到同时满足这三个条件的商品ID列表,这种交集、并集的操作,在内存里完成,效率极高,是Redis做组合检索的一大法宝。

第二种感觉:前缀搜索的“秒回”。 比如用户输入“华为”,你要立马提示“华为手机”、“华为笔记本”、“华为平板”,这种场景下,Redis的有序集合就派上用场了,你可以把所有的商品名称作为成员(member),同时给它们都设置一个相同的分数(score,比如0),关键的一步是使用ZRANGEBYLEX命令,这个命令可以按照字典序进行范围查询,你只需要命令ZRANGEBYLEX myindex [华为 [华为\xff,它就能瞬间返回所有以“华为”开头的商品名称,这里的\xff代表一个最大的字符,用来限定范围的上限,这种感觉就像是给所有数据按字母顺序排好了队,你一眼就能扫到所有以特定词开头的数据,非常高效。

第三种感觉:简单全文检索的“快刀手”。 如果我想在文章内容里搜包含“Redis”这个词的所有文章,怎么办?这就要用到倒排索引的思路了,虽然听起来专业,但用Redis实现起来并不复杂,基本思想是:我们不再记录“文章A包含了哪些词”,而是记录“词Redis被哪些文章包含了”,具体做起来,可以为每个关键词(Redis”)创建一个集合,这个集合里存放所有包含“Redis”的文章ID,当用户搜索“Redis”时,直接取出这个集合就行了,那如何建立这种索引呢?可以在文章入库时,先对文章内容进行分词,然后对于分出的每一个词,都执行SADD word:Redis article:1 article:3这样的命令,把文章ID加到对应词的集合里,搜索多个词,Redis”和“速度”,就用SINTER命令取word:Redisword:速度这两个集合的交集,得到同时包含这两个词的文章,这种方式对于小规模的文本检索,比如新闻站、博客站的内置搜索,速度非常快,而且完全自控,没有外部依赖。

第四种感觉:地理位置附近的“活地图”。 这个可能是Redis最让人眼前一亮的功能了,Redis内置了GEO数据类型,专门用来处理地理位置查询,你只需要把商户的ID和对应的经纬度存进去,比如GEOADD shops:locations 116.397128 39.916527 "shop:1",之后,想查询“我当前位置(比如经纬度116.4, 39.9)附近5公里内的所有商户”,一个命令GEORADIUS shops:locations 116.4 39.9 5 km WITHDIST就搞定了,返回结果不仅包括商户ID,还能带上距离,这种检索速度同样是微秒级,对于需要实时LBS服务的应用来说,简直是神器。

那种“靠谱”的感觉从何而来? 速度快是前提,但“靠谱”还体现在另一方面:数据持久化,Redis虽然主要工作在内存,但它提供了RDB(快照)和AOF(日志)两种持久化机制,可以根据你对数据安全性的要求进行配置,这意味着即使服务器重启,你的索引和数据也不会丢失,重新加载一下就能恢复服务,这保证了服务的可靠性。

这种感觉是有适用边界的,当你的数据量达到亿级,或者需要非常复杂的相关性排序、分词算法时,Redis就力不从心了,这时候还是得上Elasticsearch这样的专业引擎,但在千万数据量以下,尤其是对延迟极其敏感、需要实时响应的检索场景中,用Redis来实现,那种“手起刀落、结果立现”的爽快感,确实会让人觉得它是个速度飞快又相当靠谱的检索工具库。

(注:以上实现思路参考了Redis官方文档中对SET、ZSET、GEO等数据结构的说明,以及业界常见的Redis应用模式,例如使用集合求交集实现多条件查询、使用有序集合的字典序范围查询实现前缀搜索、利用集合构建简易倒排索引等。)

用Redis做检索工具类库,速度快还挺靠谱的那种感觉