Redis实现分页+多条件模糊查询组合方案

news2024/11/17 6:28:35

导言

Redis是一个高效的内存数据库,它支持包括String、List、Set、SortedSet和Hash等数据类型的存储,在Redis中通常根据数据的key查询其value值,Redis没有模糊条件查询,在面对一些需要分页、排序以及条件查询的场景时(如评论,时间线,检索等),只凭借Redis所提供的功能就不太好不处理了。微信搜索公众号:架构师指南,回复:架构师 领取资料 。

本文不对Redis的特性做过多赘述。由于之前基于业务问题需要实现基于Redis的条件查询和分页功能,在百度上查询了不少文章,基本不是只有分页功能就是只有条件查询功能的实现,缺少两者组合的解决方案。因此,本文将基于Redis提供条件查询+分页的技术解决方案。

注:本文只提供实现思路,并不提供实现的代码

本文将从四个部分进行说明:

分页实现
模糊条件查询实现
分页和模糊条件查询的组合实现
优化方案

大家可以直接跳到自己需要的部分进行阅读。

Redis的分页实现

我们通常习惯于在Mysql、Oracle这样持久化数据库中实现分页查询,但是基于某些特殊的业务场景下,我们的数据并未持久化到了数据库中或是出于查询速度上的考虑将热点数据加载到了缓存数据库中。因此,我们可能需要基于Redis这样的缓存数据库去进行分页查询。

Redis的分页查询的实现是基于Redis提供的ZSet数据结构实现的,ZSet全称为Sorted Set,该结构主要存储有序集合。下面是它的指令描述以及该指令在分页实现中的作用:

  1. ZADD:SortedSet的添加元素指令ZADD key score member [[score,member]…]会给每个添加的元素member绑定一个用于排序的值score,SortedSet就会根据score值的大小对元素进行排序。我们为通常习惯于将数据的时间属性当作score用于排序,当然大家也可以根据具体的业务场景去选择排序的目标。
  2. ZREVRANGE:SortedSet中的指令ZREVRANGE key start stop可以返回指定区间内的成员,可以用来做分页。
  3. ZREM:SortedSet的指令ZREM key member可以根据key移除指定的成员,能满足删评论的要求。

所以SortedSet用来做分页是非常适合的。下面是分页实现的演示图,包含插入新记录后的查询情况。

在这里插入图片描述

事实上,Redis中的List结构也是可以实现分页,但List无法实现自动排序,并且Zset还可以根据score进行数据筛选,取出目标score区间内数据。

所以在实现上,ZSet往往更加适合我们。当然如果你需要插入重复数据的情况下,分页就可能就需要借助List来实现了。具体使用那种结构来实现分页还是需要根据实际的业务场景来进行选择的。

Redis的多条件模糊查询实现

Redis是key-value类型的内存数据库,通过key直接取数据虽然很方便,但是并未提供像mysql那样方便的sql条件查询支持。因此我们需要借助Redis提供的结构和功能去自己实现模糊条件查询功能。

事实上,Redis的模糊条件查询是基于Hash实现的,我们可以将数据的某些条件值作为hash的key值,并数据本身作为value进行存储。然后通过Hash提供的HSCAN指令去遍历所有的key进行筛选,得到我们符合条件的所有key值(hscan可以进行模式匹配)。

为了方便,我们通常将符合条件的key全部放入到一个Set或是List中。这样一来,我们就可以根据得到的key值去取出相应的数据了。下面是模糊查询的演示图(其中field中的命名规则为<id>:<姓名>:<性别>,value为用户详情的json串)。

查询所有性别为女的用户

在这里插入图片描述

查询所有名字中姓阿的用户

在这里插入图片描述

HSCAN虽然为我们提供了模式匹配的功能,但这种匹配是基于遍历实现的,每一次匹配都需要遍历全部的key,效率上并不高。因此在下面一节会这方面进行补充,本节只谈如何实现模糊匹配。

Redis的分页+多条件模糊查询组合实现

前面分别单独叙述了如何实现Redis的分页和多条件某查询。在实际使用中,单独使用ZSet实现分页已经能够展现不错的性能了,但存在一个问题是我们所分页的数据往往是伴随着一些动态的筛选条件的,而ZSet并不提供这样的功能。

面对这种情况,我们通常有两种解决方案:

  1. 如果数据已经存储在了持久化数据库中,我们可以每次在数据库中做好条件查询再将数据放入Redis中进行分页。

  2. 在Redis中实现多条件模糊查询并分页。

前者方案其实是一个不错的选择,但缺点在于数据有时候并不一定都在持久化数据库中。在有些业务场景下,我们的数据为了展现更好的并发性以及高响应,我们的数据会先放置在缓存数据库中,等到某个时间或者满足某种条件时再持久化到数据库中。

在这种情况下我们第一个方案就不起作用了,需要使用第二个方案。因此,下面将介绍如何实现多条件模糊查询的基础上进行分页。

实现思路

首先我们可以采用多条件模糊查询章节所说的方式,将我们所涉及到的条件字段作为hash的field,而数据的内容则作为对应value进行存储(一般以json格式存储,方便反序列化)。

我们需要实现约定好查询的格式,用前面一节的例子来说,field中的命名规则为<id>:<姓名>:<性别>,我们每次可以通过"*"来实现我们希望的模糊匹配条件,比如“*:*:男”就是匹配所有男性数据,“100*:*:*”就是匹配所有id前缀为100的用户。

当我们拿到了匹配串后我们先去Redis中寻找是否存在以该匹配串为key的ZSet,如果没有则通过Redis提供的HSCAN遍历所有hash的field,得到所有符合条件的field,并将其放入一个ZSet集合,同时将这个集合的key设置为我们的条件匹配串。如果已经存在了,则直接对这个ZSet进行分页查询即可。对ZSet进行分页的方式已经在前面叙述过了。通过这样的方式我们就实现了最简单的分页+多条件模糊查询。

在这里插入图片描述

上图中,由于并未在缓存数据库中找到符合的ZSet集合,我们将根据匹配串生成一个新的集合用于分页。

性能优化方案

虽然上文实现了多条件模糊查询+分页的功能,但是在时间开发中,我们不能无限制的生成新的集合,因为匹配串是很多样化的,这会给缓存带来巨大的压力。

因此我们在生成集合时可以赋予这个集合一个过期时间,到期集合会自动销毁。因为根据时间局部性原理,我们在一段时间内不访问的数据大概率在很长一顿时间内也不会再访问。而对于命中的集合,我们将更新其过期时间。

同时,我们数据的实时性也是一个问题,因为我们的集合是在生成集合时的Hash内容决定的,对于新插入到Hash的数据,集合是无法探知的,因此有两种解决方案:

  1. 第一种是插入到Hash时同时再插入到其他相应的集合中,保证数据一直是最新的,这种方式需要增加特殊前缀用于识别,否则我们也不清楚到底要插入到哪些集合中。

  2. 第二种方式是定时更新,这种方式比较省力,但无法保证分页数据的实时性。因此具体怎么选择还是取决于业务场景。

总结

本文大概地描述了实现分页和多条件模糊查询的方案,希望能够对大家有所帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/757104.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

spring boot 集成dubbo

本demo使用spring boot 2.4.1版本集成 dubbo 2.7.15 1.创建maven项目及其子模块 父工程pom.xml <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation"http://maven.ap…

个人微信开发API,微信机器人开发

安卓微信的api&#xff0c;个人微信开发API协议&#xff0c;微信 ipad &#xff0c;微信ipad协议&#xff0c;微信web版接口api&#xff0c;微信网页版接口&#xff0c;微信开发sdk&#xff0c;微信开发API&#xff0c;微信协议&#xff0c;微信接口文档&#xff0c;网页个人微…

不清晰的照片怎么变清晰?这几个方法轻松处理!

大家都会碰到老旧照片放大后变得模糊不清的情况&#xff0c;可惜我们无法在网上下载原图&#xff0c;这是我们自己的照片。那有没有简便的方法修复模糊照片呢&#xff1f;很多人会提到使用PS&#xff0c;但操作复杂需要基本技能。除了PS&#xff0c;还有其他方法修复模糊照片。…

图片速览 Deep k-Means: Jointly clustering with k-Means and learning representations

本文探讨了联合聚类与学习的问题 交涉。正如之前的几项研究表明&#xff0c;学习 既忠实于要聚类和调整的数据的表示形式 到聚类算法可以导致更好的聚类性能&#xff0c;所有的 更重要的是&#xff0c;这两项任务是联合执行的。我们在这里提出这样一个 方法的k-基于连续重新参数…

每天一道C语言编程练习(5):尼科彻斯定理

题目描述 验证尼科彻斯定理&#xff0c;即&#xff1a;任何一个整数m的立方都可以写成m个连续奇数之和。 输入格式 任一正整数 输出格式 该数的立方分解为一串连续奇数的和 样例输入 13 样例输出 13*13*132197157159161163165167169171173175177179181 代码如下&#…

【前端知识】React 基础巩固(二十七)——Fragment

React 基础巩固(二十七)——Fragment Fragment Fragment 允许将子列表分组&#xff0c;而无需向 DOM 添加额外节点可以采用语法糖<></>来替代 Fragment&#xff0c;但在需要添加 key 的场景下不能使用此短语 import React, { PureComponent, Fragment } from &q…

VUE之基本部署及VScode常用插件

参考资料&#xff1a; 参考视频 VScode常用插件清单 node.js官网 node.js官网中文版 VUE官方文档 VScode常用插件&#xff1a; VScode常用插件详解见上述连接&#xff0c;插件列表如下&#xff1a; VScode的注释/取消注释快捷键为&#xff1a;Ctrl/ VUE的基本安装部署--…

shardingsphere mybatisplus properties和yml配置实现、分页配置

shardingsphere mybatisplus properties和yml配置实现 目录结构 model package com.oujiong.entity;import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Data; import org.springframework.format…

【JAVA】——环境配置安装

一.Java简介 1.1 Java的特点 Java是一种跨平台、面向对象的程序设计语言&#xff0c;用它编写的程序可以在任何计算机操作系统和支持Java的硬件设备上运行。Java是一种通过解释方式来执行的语言&#xff0c;那么什么是解释方式呢&#xff1f; 程序员编写的代码一般都是用高级语…

程序员的自我修养(2)

目标文件的学习 1.什么是目标文件以及格式 目标文件为编译器编译后生成的文件&#xff0c;就是window下的.obj&#xff0c;linux下的.o文件。与可执行文件格式几乎一样&#xff0c;因为只是缺少链接过程。所以可执行文件&#xff0c;动态链接库&#xff0c;静态链接库&#xf…

B070-项目实战-用户模块--手机注册

目录 用户模块需求分析静态网站部署与调试两种前端项目的部署两种前端项目的调试(热部署)创建静态web项目 注册分析与设计分析需求设计 界面设计&#xff08;ui&#xff09;设计表&#xff08;后台&#xff09; 流程设计&#xff08;后台&#xff09;三范式表设计流程设计 相关…

英语动词-分类及应用

文章目录 1.实义动词系动词情态动词 1.实义动词 实义动词是表示具体动词的词。 常见的分类&#xff1a;及物动词和不及物动词。 1.及物动词&#xff1a;transitive verb后面直接加宾语&#xff0c;并且必须加宾语。比如&#xff1a;I love you.I buy a book. 2.不及物动词&…

AI 智能对话 - ChatGLM2-6B 本地搭建入门

前情提要 这一个月来干了啥事情呢&#xff1f;AI 绘画搞了2周左右&#xff0c;SD 建筑绘图&#xff0c;训练 LORA &#xff0c;模型控制基本也上手了&#xff0c;可以按照预期生成自己想要的东西&#xff0c;那种控制感是挺开心的&#xff0c;不然你输入一句话生成 AI 图片完全…

Linux进程(三)---深入理解进程地址空间

目录 地址空间的划分及验证 所谓的地址空间是内存吗&#xff1f; 一种奇怪的现象(虚拟地址的引入) 什么是进程地址空间&#xff1f; 我们平常访问到的内存是物理内存吗&#xff1f; 深入理解区域划分 再谈奇怪的现象 fork()中为什么一个变量可以同时保存两个不同的值 …

网络安全—入职大厂经验之谈

大三想去实习&#xff0c;趁现在该干什么才能去大厂实习呢&#xff1f;想做一些事丰富一下自己的简历&#xff0c;只有打ctf&#xff1f;还是挖洞&#xff1f;非常迷茫。 或者入职转行网络安全行业应该怎么做&#xff1f;对于接下来的职业规划学习计划有什么打算&#xff1f; …

PETRv2: A Unified Framework for 3D Perception from Multi-Camera Images

PETRv2: A Unified Framework for 3D Perception from Multi-Camera Images 作者单位 旷视 目的 本文的目标是 通过扩展 PETR&#xff0c;使其有时序建模和多任务学习的能力 以此建立一个 强有力且统一的框架。 本文主要贡献&#xff1a; 将 位置 embedding 转换到 时序表…

漏洞复现 || Bitrix cms文件上传

免责声明 技术文章仅供参考&#xff0c;任何个人和组织使用网络应当遵守宪法法律&#xff0c;遵守公共秩序&#xff0c;尊重社会公德&#xff0c;不得利用网络从事危害国家安全、荣誉和利益&#xff0c;未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此…

Go语言之流程控制语句,for循环

程序是由语句构成&#xff0c;而流程控制语句 是用来控制程序中每条语句执行顺序的语句。可以通过控制语句实现更丰富的逻辑以及更强大的功能。几乎所有编程语言都有流程控制语句&#xff0c;功能也都基本相似。 其流程控制方式有 顺序结构,分支结构,循环结构 1、switch比if el…

javaWeb之文件上传和下载

文件上传下载(场景): * 文件上传 * 客户端 * 文件上传页面(form) * 请求方式一定是POST. * 文件上传域(<input typefile>)必须具有name属性. * 表单的enctype属性值设置为"multipart/form-data". * 扩展:浏览器内核产品不同(不建…

剖析C语言字符串函数(超全)

目录 前言&#xff1a; 一、strlen函数 功能&#xff1a; 参数和返回值&#xff1a; 注意事项&#xff1a; 返回值是无符号的易错点&#xff1a; strlen函数的模拟实现 1、计数器算法 2、递归算法 3、指针减去指针 二、strcpy函数 功能&#xff1a; 参数和返回值 …