0

0

怎么用Redis实现搜索接口

王林

王林

发布时间:2023-06-02 21:31:21

|

1135人浏览过

|

来源于亿速云

转载

对于后端开发人员来讲使用一条sql就可以实现列表查询的接口,如果查询条件很复杂,表库设计不合理,会导致查询很困难,这篇文章和大家分享一下用redis实现搜索接口。

下面以一个例子开始,这是某购物网站的搜索条件,如果让你实现这样的一个搜索接口,你会如何实现?

当然你说借助搜索引擎,像 Elasticsearch 之类的,你完全可以实现。但我这里想说的是,如果要你自己实现呢?

怎么用Redis实现搜索接口

从上图中可以看出,搜索总共分为 6 大类,每大类中又分了各个子类。

在这种情况下,筛选过程取各大类条件的交集,并考虑各子类中单选、多选和自定义的情况,以输出符合条件的结果集。

好了,既然需求很明确了,我们就开始来实现。

实现 1

率先登场是小 A 同学,他是写 SQL 方面的“专家”。小 A 信心满满的说:“不就是一个查询接口吗?看着条件很多,但凭着我丰富的 SQL 经验,这点还是难不倒我的。”

于是乎就写出了下面这段代码(这里以 MySQL 为例):

select ... from table_1 
left join table_2 
left join table_3 
left join (select ... from table_x where ...) tmp_1 
... 
where ... 
order by ... 
limit m,n

代码在测试环境跑了一把,结果好像都匹配上了,于是准备上预发。这一上预发,问题就开始暴露出来。

预发为了尽可能的逼真线上环境,所以数据量自然而然要比测试大的多。所以这么一个复杂的 SQL,它的执行效率可想而知。测试同学果断把小 A 的代码给打了回来。

实现 2

总结了小 A 失败的教训,小 B 开始对 SQL 进行了优化,先是通过了 explain 关键字进行 SQL 性能分析,对该加索引的地方都加上了索引。

同时将一条复杂 SQL 拆分成了多条 SQL,计算结果在程序内存中进行计算。

伪代码如下:

$result_1 = query('select ... from table_1 where ...'); 
$result_2 = query('select ... from table_2 where ...'); 
$result_3 = query('select ... from table_3 where ...'); 
... 
 
$result = array_intersect($result_1, $result_2, $result_3, ...);

这种方案从性能上明显比第一种要好很多,可是在功能验收的时候,产品经理还是觉得查询速度不够快。

小 B 自己也知道,每次查询都会向数据库查询多次,而且有些历史原因,部分条件是做不到单表查询的,所以查询等待的时间是避免不了的。

实现 3

小 C 从上面的方案中看到了优化的空间。他发现小 B 在思路上是没问题的,将复杂条件拆分,计算各个子维度的结果集,最后将所有的子结果集进行一个汇总合并,得到最终想要的结果。

于是他突发奇想,能否事先将各个子维度的结果集给缓存起来,这要查询的时候直接去取想要的子集,而不用每次去查库计算。

这里小 C 采用 Redis 来存储缓存数据,用它的主要原因是,它提供了多种数据结构,并且在 Redis 中进行集合的交并集操作是一件很容易的事情。

具体方案,如图所示:

怎么用Redis实现搜索接口

这里每个条件都事先将计算好的结果集 ID 存入对应的 Key 中,选用的数据结构是集合(Set)。

查询操作包括:

    • 子类单选:直接根据条件 Key,获取对应结果集。

    • 子类多选:根据多个条件 Key,进行并集操作,获取对应结果集。

    • 最终结果:将获取的所有子类结果集进行交集操作,得到最终结果。

这其实就是所谓的反向索引。这里会发现,漏了一个价格的条件。从需求中可知,价格条件是个区间,并且是无穷举的。

BJXSHOP网上开店专家
BJXSHOP网上开店专家

BJXShop网上购物系统是一个高效、稳定、安全的电子商店销售平台,经过近三年市场的考验,在中国网购系统中属领先水平;完善的订单管理、销售统计系统;网站模版可DIY、亦可导入导出;会员、商品种类和价格均实现无限等级;管理员权限可细分;整合了多种在线支付接口;强有力搜索引擎支持... 程序更新:此版本是伴江行官方商业版程序,已经终止销售,现于免费给大家使用。比其以前的免费版功能增加了:1,整合了论坛

下载

所以上述的这种穷举条件的 Key-Value 方式是做不到的。在此处,我们使用了 Redis 的有序集合(Sorted Set)这一数据结构进行了实现

怎么用Redis实现搜索接口

将所有商品加入 Key 为价格的有序集合中,值为商品 ID,每个值对应的分数为商品价格的数值。

这样在 Redis 的有序集合中就可以通过 ZRANGEBYSCORE 命令,根据分数(价格)区间,获取相应结果集。

至此,方案三的优化已全部结束,将数据的查询与计算通过缓存的手段,进行了分离。

在每次查找时,只需要简单的查找 Redis 几次就能得出结果。查询速度上符合了验收的要求。

扩展

①分页

这里你或许发现了一个严重的功能缺陷,列表查询怎么能没有分页。是的,我们马上来看 Redis 是如何实现分页的。

分页主要涉及排序,这里简单起见,就以创建时间为例。如图所示:

怎么用Redis实现搜索接口

图中蓝色部分是以创建时间为分值的商品有序集合,蓝色下方的结果集即为条件计算而得的结果,通过 ZINTERSTORE 命令,赋结果集权重为 0,商品时间结果为 1,取交集而得的结果集赋予创建时间分值的新有序集合。

对新结果集的操作即能得到分页所需的各个数据:

    • 页面总数为:ZCOUNT 命令。

    • 当前页内容:ZRANGE 命令。

    • 若以倒序排列:ZREVRANGE命令。

②数据更新

关于索引数据更新的问题,有两种方式来进行。一种是通过商品数据的修改,来即时触发更新操作,一种是通过定时脚本来进行批量更新。

这里要注意的是,关于索引内容的更新,如果暴力的删除 Key,再重新设置 Key。

因为 Redis 中两个操作不会是原子性进行的,所以中间可能存在空白间隙,建议采用仅移除集合中失效元素,添加新元素的方式进行。

③性能优化

Redis 是内存级操作,所以单次的查询会很快。但是如果我们的实现中会进行多次的 Redis 操作,Redis 的多次连接时间可能是不必要时间消耗。

通过使用 MULTI 命令,开启一个事务,将 Redis 的多次操作放在一个事务中,最后通过 EXEC 来进行原子性执行。

注意:这里所谓的事务,只是将多个操作在一次连接中执行,如果执行过程中遇到失败,是不会回滚的。

总结

这里只是一个采用 Redis 优化查询搜索的一个简单 Demo,和现有的开源搜索引擎相比,它更轻量,学习成本页相应低些。

其次,它的一些思想与开源搜索引擎是类似的,如果再加上词语解析,也可以实现类似全文检索的功能。

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

679

2023.10.12

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

320

2023.10.27

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

346

2024.02.23

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

1095

2024.03.06

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

357

2024.03.06

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

675

2024.04.07

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

573

2024.04.29

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

415

2024.04.29

高德地图升级方法汇总
高德地图升级方法汇总

本专题整合了高德地图升级相关教程,阅读专题下面的文章了解更多详细内容。

9

2026.01.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
进程与SOCKET
进程与SOCKET

共6课时 | 0.3万人学习

Redis+MySQL数据库面试教程
Redis+MySQL数据库面试教程

共72课时 | 6.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号