如何在Redis中实现分页排序查询过程解析

Redis是一个高效的内存数据库,它支持包括String、List、Set、SortedSet和Hash等数据类型的存储,在Redis中通常根据数据的key查询其value值,Redis没有条件查询,在面对一些需要分页或排序的场景时(如评论,时间线),Redis就不太好不处理了。

前段时间在项目中需要将每个主题下的用户的评论组装好写入Redis中,每个主题会有一个topicId,每一条评论会和topicId关联起来,得到大致的数据模型如下:

{
  topicId: 'xxxxxxxx',
  comments: [
    {
      username: 'niuniu',
      createDate: 1447747334791,
      content: '在Redis中分页',
      commentId: 'xxxxxxx',
      reply: [
        {
          content: 'yyyyyy'
          username: 'niuniu'
        },
        ...
      ]
    },
    ...
  ]}

将评论数据从MySQL查询出来组装好存到Redis后,以后每次就可以从Redis获取组装好的评论数据,从上面的数据模型可以看出数据都是key-value型数据,无疑要采用hash进行存储,但是每次拿取评论数据时需要分页而且还要按createDate字段进行排序,hash肯定是不能做到分页和排序的。

那么,就挨个看一下Redis所支持的数据类型:

Hash

主要用于存储key-value型数据,评论模型中全是key-value型数据,所以在这里Hash无疑会用到。

List

主要用于存储一个列表,列表中的每一个元素按元素的插入时的顺序进行保存,如果我们将评论模型按createDate排好序后再插入List中,似乎就能做到排序了,而且再利用List中的LRANGE key start stop指令还能做到分页。嗯,到这里List似乎满足了我们分页和排序的要求,但是评论还会被删除,就需要更新Redis中的数据,如果每次删除评论后都将Redis中的数据全部重新写入一次,显然不够优雅,效率也会大打折扣,如果能删除指定的数据无疑会更好,而List中涉及到删除数据的就只有LPOP和RPOP这两条指令,但LPOP和RPOP只能删除列表头和列表尾的数据,不能删除指定位置的数据,所以List也不太适合。

Set

主要存储无序集合,无序!排除。

SortedSet

主要存储有序集合,SortedSet的添加元素指令ZADD key score member [[score,member]…]会给每个添加的元素member绑定一个用于排序的值score,SortedSet就会根据score值的大小对元素进行排序,在这里就可以将createDate当作score用于排序,SortedSet中的指令ZREVRANGE key start stop又可以返回指定区间内的成员,可以用来做分页,SortedSet的指令ZREM key member可以根据key移除指定的成员,能满足删评论的要求,所以,SortedSet在这里是最适合的。

所以,我需要用到的数据类型有SortSet和Hash,SortSet用于做分页排序,Hash用于存储具体的键值对数据,我画出了如下的结构图:

在上图的SortSet结构中将每个主题的topicId作为set的key,将与该主题关联的评论的createDate和commentId分别作为set的score和member,commentId的顺序就根据createDate的大小进行排列。 当需要查询某个主题某一页的评论时,就可主题的topicId通过指令zrevrange topicId (page-1)×10 (page-1)×10+perPage这样就能找出某个主题下某一页的按时间排好顺序的所有评论的commintId。page为查询第几页的页码,perPage为每页显示的条数。 当找到所有评论的commentId后,就可以把这些commentId作为key去Hash结构中去查询该条评论对应的内容。 这样就利用SortSet和Hash两种结构在Redis中达到了分页和排序的目的。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Redis利用Pipeline加速查询速度的方法

    1. RTT Redis 是一种基于客户端-服务端模型以及请求/响应协议的TCP服务.这意味着通常情况下 Redis 客户端执行一条命令分为如下四个过程: 发送命令 命令排队 命令执行 返回结果 客户端向服务端发送一个查询请求,并监听Socket返回,通常是以阻塞模式,等待服务端响应.服务端处理命令,并将结果返回给客户端.客户端和服务端通过网络进行连接.这个连接可以很快,也可能很慢.无论网络如何延迟,数据包总是能从客户端到达服务端,服务端返回数据给客户端. 这个时间被称为 RTT (Round

  • Redis分析慢查询操作的实例教程

    什么是慢查询 慢查询的作用:通过慢查询分析,找到有问题的命令进行优化. 和mysql的慢SQL日志分析一样,redis也有类似的功能,来帮助定位一些慢查询操作. Redis slowlog是Redis用来记录查询执行时间的日志系统. 查询执行时间指的是不包括像客户端响应(talking).发送回复等IO操作,而单单是执行一个查询命令所耗费的时间. 另外,slow log保存在内存里面,读写速度非常快,因此你可以放心地使用它,不必担心因为开启slow log而损害Redis的速度. 慢查询日志四个

  • php-redis中的sort排序函数总结

    很多人把redis当成一种数据库,其实是利用redis来构造数据库的模型,有那种数据库的味道.但是在怎么构建还是key和value的关系,与真正的关系型数据库还是不一样的. 效率高,不方便:方便的,效率不高:又方便,效率又高的要花钱. php-redis里面的sort函数,在做web的时候取数据还是比较方便,有点关系型数据库的味道.在说sort前,先说一下前面漏的几个比较常用的函数.  1) keys 描述:查找符合给定模式的key 参数:匹配模式 返回值:符合给定模式的key列表 2) mse

  • Spring AOP实现Redis缓存数据库查询源码

    应用场景 我们希望能够将数据库查询结果缓存到Redis中,这样在第二次做同样的查询时便可以直接从redis取结果,从而减少数据库读写次数. 需要解决的问题 操作缓存的代码写在哪?必须要做到与业务逻辑代码完全分离. 如何避免脏读? 从缓存中读出的数据必须与数据库中的数据一致. 如何为一个数据库查询结果生成一个唯一的标识?即通过该标识(Redis中为Key),能唯一确定一个查询结果,同一个查询结果,一定能映射到同一个key.只有这样才能保证缓存内容的正确性 如何序列化查询结果?查询结果可能是单个实体

  • 在ssm项目中使用redis缓存查询数据的方法

    在项目中常常需要后台程序的持久层查询数据库来获取数据,然后将数据交给服务层.控制层,最后才交给视图层.如果数据访问缓慢,就会影响程序的运行. 为了加快程序的运行,可以将数据放入缓存中,包括数据缓存和页面缓存. 所谓缓存,就是将程序或系统经常要调用的对象存在内存中,一遍其使用时可以快速调用,不必再去创建新的重复的实例.这样做可以减少系统开销,提高系统效率. 其中页面缓存主要是oscache,可以整页或者指定网页某一部分缓存,同时指定他的过期时间,这样在此时间段里面访问的数据都是一样的 . 数据缓存

  • Redis sort 排序命令详解

    本文介绍redis排序命令 redis支持对list,set,sorted set元素的排序 sort 排序命令格式: sort key [BY pattern] [LIMIT start count] [GET pattern] [ASC|DESC] [ALPHA] [STORE dstkey] 1) sort key (list) 这是最简单的情况,没有任何选项对集合自身元素排序并返回排序结果,默认为value升序. 示例: 复制代码 代码如下: 127.0.0.1:6379> lpush

  • Redis高级玩法之利用SortedSet实现多维度排序的方法

    说明:本次实践基于Redis版本3.2.11. 关于SortedSet 首先,我们都知道Redis的SortedSet是可以根据score进行排序的,以手机应用商店的热门榜单排序为例,根据下载量倒序排列,其简单用法如下: 127.0.0.1:6379> zadd TopApp 12000000 wechat (integer) 1 127.0.0.1:6379> zadd TopApp 8000000 taobao 10000000 alipay (integer) 2 127.0.0.1:6

  • Node.js操作redis实现添加查询功能

    在实际开发中,免不了要操作mysql,mongodb,redis等数据存储服务器.这里先简单介绍如何操作redis. 一个例子 关于redis服务端的安装这里不再介绍,重点不在这里.感兴趣的可以自行安装. 对于一个新的模块,我们需要在我们的项目中先安装redis模块才能用. 命令 cnpm install redis 新建一个redis.js的文件,代码如下: //引入redis var redis = require("redis"); //创建redis客户端 var client

  • 使用Redis有序集合实现IP归属地查询详解

    工作中经常遇到一类需求,根据 IP 地址段来查找 IP 对应的归属地信息.如果把查询过程放到关系型数据库中,会带来很大的 IO 消耗,速度也不能满足,显然是不合适的. 那有哪些更好的办法呢?为此做了一些尝试,下面来详细说明. 构建索引文件 在 GitHub 上看到一个ip2region 项目,作者通过生成一个包含有二级索引的文件来实现快速查询,查询速度足够快,毫秒级别.但如果想更新地址段或归属地信息,每次都要重新生成文件,并不是很方便. 不过还是推荐大家看看这个项目,其中建索引的思想还是很值得学

  • 如何在Redis中实现分页排序查询过程解析

    Redis是一个高效的内存数据库,它支持包括String.List.Set.SortedSet和Hash等数据类型的存储,在Redis中通常根据数据的key查询其value值,Redis没有条件查询,在面对一些需要分页或排序的场景时(如评论,时间线),Redis就不太好不处理了. 前段时间在项目中需要将每个主题下的用户的评论组装好写入Redis中,每个主题会有一个topicId,每一条评论会和topicId关联起来,得到大致的数据模型如下: { topicId: 'xxxxxxxx', comm

  • MybatisPlus分页排序查询字段带有下划线的坑及解决

    目录 MybatisPlus分页排序查询字段带有下划线 MybatisPlus字段名称有下划线查询为null 原因分析 解决方案 MybatisPlus分页排序查询字段带有下划线 如果使用MybatisPlus的自动转驼峰命名法,分页排序查询的字段带有下划线时,会出问题. page = new Page<>(pageNo, pageSize); OrderItem orderItem = new OrderItem(); orderItem.setColumn("create_dat

  • 关于在Redis中使用Pipelining加速查询的问题

    目录 Request/Response protocols and RTT Redis Pipelining It’s not just a matter of RTT Some real world code example Pipelining VS Scripting Appendix: Why are busy loops slow even on the loopback interface? 思考 参考 Request/Response protocols and RTT Redis

  • Mybatis pagehelper分页插件使用过程解析

    这篇文章主要介绍了mybatis pagehelper分页插件使用过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 使用过mybatis的人都知道,mybatis本身就很小且简单,sql写在xml里,统一管理和优化.缺点当然也有,比如我们使用过程中,要使用到分页,如果用最原始的方式的话,1.查询分页数据,2.获取分页长度,也就是说要使用到两个方法才能完成分页.有没有更更好的分页方式的,pagehelper分页插件因此而诞生,他的原理是利用

  • JavaScript中new运算符的实现过程解析

    这篇文章主要介绍了JavaScript中new运算符的实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 废话不多说直接进入正题,首先我们需要先知道new运算符到底做了哪些事情,再来模拟它实现这一功能. 1. 建立一个空的Object对象: 2. 把这个空对象用__proto__链接到原型 3. 用apply绑定对象的this指向 4. 返回新的对象 知道了new的具体过程之后,我们就可以来试一下用代码实现这一过程. // 传参 New

  • java使用elasticsearch分组进行聚合查询过程解析

    这篇文章主要介绍了java使用elasticsearch分组进行聚合查询过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 java连接elasticsearch 进行聚合查询进行相应操作 一:对单个字段进行分组求和 1.表结构图片: 根据任务id分组,分别统计出每个任务id下有多少个文字标题 1.SQL:select id, count(*) as sum from task group by taskid; java ES连接工具类 p

  • DoytoQuery中的分页排序方案示例详解

    目录 引言 分页 分页接口 排序 请求对象 响应对象 小结 引言 分页和排序是数据库提供的两项基本的查询功能. 以MySQL为例,一条典型的SQL查询语句如下: SELECT * FROM t_user ORDER BY create_time DESC, username ASC LIMIT 10 OFFSET 20 那么在前后端交互中,前端应该如何向后端传递分页和排序有关的信息呢?需要传递哪些参数?参数的意义和格式又是什么? 分页 分页的语句为LIMIT 10 OFFSET 20,其中10为

  • 如何在django中实现分页功能

    1.在html页面中导入js文件和css文件 <link rel="stylesheet" href="../../../static/css/jquery.pagination.css" rel="external nofollow" > <script type="text/javascript" src="../../../static/js/jquery-1.12.4.min.js"

  • Django filter动态过滤与排序实现过程解析

    前期准备 在虚拟开发环境中安装: pip install django-filter 在Django的项目配置文件中安装并配置django_filters应用: INSTALLED_APPS = [ ... 'django_filters', ] REST_FRAMEWORK = { # 过滤器默认后端 'DEFAULT_FILTER_BACKENDS': ( 'django_filters.rest_framework.DjangoFilterBackend',), } 快速使用 model.

  • Spring Data JPA分页复合查询原理解析

    Spring Data JPA是Spring Data家族的一部分,可以轻松实现基于JPA的存储库. 此模块处理对基于JPA的数据访问层的增强支持. 它使构建使用数据访问技术的Spring驱动应用程序变得更加容易. 在相当长的一段时间内,实现应用程序的数据访问层一直很麻烦. 必须编写太多样板代码来执行简单查询以及执行分页和审计. Spring Data JPA旨在通过减少实际需要的工作量来显著改善数据访问层的实现. 作为开发人员,您编写repository接口,包括自定义查找器方法,Spring

随机推荐