Redis滚动分页的使用

news2024/10/5 22:03:47

Feed流

关注推送也叫Feed流。通过无限下拉刷新获取新的信息。

Feed流产品常见有两种模式:

Timeline: 不做内容筛选,简单的按照内容发布时间排序,常用于好友或关注。例如朋友圈

优点:信息全面,不会有缺失。并且实现也相对简单

缺点:信息噪音较多,用户不一定感兴趣,内容获取效率低。

智能排序:利用智能算法屏蔽掉违规的、用户不感兴趣的内容。推送用户感兴趣信息来吸引用户

优点:投喂用户感兴趣信息,用户粘度很高,容易沉迷

缺点:如果算法不精准,可能起到反作用。

Timeline模式的实现方案有三种:拉模式、推模式、推拉结合

拉模式

拉模式也叫读扩散。这是因为,进行阅读的用户本身不接受任何数据,当开始阅读时,才会将关注的内容拉取。模型图如下

优点:

节省内存空间,因为收件箱阅读结束后就会清空,相当于消息只在个人的发件箱中保存了一份。

缺点:

耗时较久,因为除了需要拉取消息外,还需要对消息进行排序,这个过程比较耗时,当一个用户关注的人较多,一次性拉取的消息过多这个耗时会更久。

推模式

推模式也叫写扩散。这是因为当一个人发表动态时,会将该信息推送到每个关注他的收件箱。

优点:

延时低,当粉丝读取消息时,已经是一个排序好的数据。

缺点:

占用内存空间,同一份消息需要存储n份。当一个人粉丝很多时,存储过多重复数据。

推拉结合

也叫读写混合,兼具推拉两种模式的优点。

粉丝数量多的账号拥有一个发件箱,发件箱会推送给活跃用户的收件箱,而对于普通用户不经常使用的,采取拉模式,当开始阅读时,主动从发件箱中拉去。对于粉丝数量不多的一般用户,直接采取推模式即可。

三种模式对比

拉模式

推模式

推拉结合

写比例

读比例

用户读取延迟

实现难度

复杂

简单

很复杂

使用场景

很少使用

用户量少,没有大V

过千万用户量,存在大V

Feed流的分页问题

我们通常对一个页面能够展示的数据有一定限制,因此当收件箱存在很多数据时,我们需要实现分页功能。如何实现Feed流的分页功能是一个复杂的问题,如果采用MyBatis中的分页插件是不能满足分页功能的,因为Feed流是一个动态的,数据会不断更新,因此数据的角标会不停更新,当我们需要查询第5-10条的数据时,可能又保存了一个新的数据到数据库,从而导致我们分页查找的数据存在与上一次查询的数据重复的问题,具体问题流程图如下。

因此我们需要采用滚动分页,所谓滚动分页就是每次查询过数据库后,我们需要记录这一次查询结果的最后一条数据,下一次查询时,从上一次的最后一条开始往后查。流程图如下

而满足滚动分页的Redis数据结构只有ScoreSet,记录每次执行结束后最后一个数据的分数,下一次查询时,从该分数的下一个开始查询。因为我们要根据时间进行排序,因此,这里的分数应该是时间戳。那么实现滚动分页的语句应该为

ZRANGEBYSCORE key -inf +inf WITHSCORES LIMT offset count

命令解释:

  • -inf:表示最小值
  • +inf:表示最大值,这样可以在不知道分数的情况下,对全部的值进行操作
  • offset:偏移量,表示当前数据之后第几个偏移量后开始获取元素
  • count:需要获取元素的数量

在我们实际开发中,还需要注意一个问题就是score重复的问题。对于score重复我们应该记录本次查询结果中,最小score的数量,来充当下一次的偏移量,比如说我在Redis中存在如下几个数据

如果我们一次查询3条数据,在记录到当前查询的最小分数后,下次查询时指定偏移量为1时,那么可能会存在如下问题

zrevrangebyscore feed:test +inf -inf withscores limit 0 3

此时我们查找到m5与n5,接下来我们应该从i5开始查找,那么如果将偏移量设置为 1 进行测试观察结果

zrevrangebyscore feed:test 5 -inf withscores limit 1 3

可以看到,他是从第一个分数等于5的开始计算,获取之后的三个元素,因此,我们需要在开发中,对偏移量进行计算,方便我们下次进行查询时设置偏移量,大概的Java代码如下

//lastId指的是本次查询的最小分数值
//offset指的是偏移量
public Result queryPage(Long lastId, Integer offset) {
    //2、查询属于自己的收件箱
    Set<ZSetOperations.TypedTuple<String>> typedTuples =
            stringRedisTemplate.opsForZSet()
                    .reverseRangeByScoreWithScores(FEED_KEY, 0, lastId, offset, 3);
    //如果set等于null
    if (typedTuples==null || typedTuples.isEmpty()){
        return Result.ok();
    }
    //3、解析数据minTime
    //记录最小分数
    long score=0;
    //记录偏移量
    int os=1;
    List<String> pageValue=new ArrayList<>(typedTuples.size());//设置列表长度为typedTuples的大小
    for (ZSetOperations.TypedTuple<String> typedTuple : typedTuples) {
        String value = typedTuple.getValue();
        //将查询的数据存储在集合中
        pageValue.add(value);
        //记录当前分数
        long time = typedTuple.getScore().longValue();
        if (time==score){
        	//如果当前分数相同,则偏移量加1 
            os++;
        }else {
            //如果不同,说明当前的分数更低,刷新偏移量
            score=time;
            os=1;
        }
    }
    //返回最小的分数以及偏移量供下次调用时使用。
    Pages pages = new Pages();
    pages.setPageValue(pageValue);
    pages.setLastId(score);
    pages.setOffset(os);
    return Result.ok(pageValue);
}

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

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

相关文章

JVM 运行时参数

面试题 JVM的参数&#xff0c;你知道的说一下 (百度) 说说你知道的几种主要的JVM参数&#xff08;京东&#xff09; JVM调优调的哪些参数&#xff1f;在哪里写这些参数&#xff1f; &#xff08;亚信&#xff09; 内存调优参数都有什么&#xff1f;&am…

【日常总结】root ssh第一天远程正常,次日无法访问,修正 PermitRootLogin yes 后 ,ssh root 还是不能访问

一、环境 二、场景 三、原因 四、解决方案 1. 客户设置账号过期时间 2. 修正 PermitRootLogin yes 后 &#xff0c;ssh root 还是不能访问 一、环境 客户项目&#xff1a;独立外网IP 服务器&#xff1a;Ubuntu 22.04.3 LTS ssh&#xff1a;外网映射到服务器22端口 二、…

我从来不理解JavaScript闭包,但我用了它好多年

前言 &#x1f4eb; 大家好&#xff0c;我是南木元元&#xff0c;热衷分享有趣实用的文章&#xff0c;希望大家多多支持&#xff0c;一起进步&#xff01; &#x1f345; 个人主页&#xff1a;南木元元 你是否学习了很久JavaScript但还没有搞懂闭包呢&#xff1f;今天就来聊一下…

精准捕捉异常时刻——从写好事件标题与内容开始

写在前面 在讨论如何写好监控器配置时的事件通知内容之前&#xff0c;需要明确这样一个逻辑&#xff1a; 当监控器检测规则生效后&#xff0c;它会针对系统业务数据进行一系列聚合数据处理并以事件的形式留存。这些事件记录可以理解为当前监控器检测对象发出的异常信号的承载…

WPS Office JS宏实现Excel转换为JSON格式数据

通过Excel JS宏&#xff0c;将表格中的数据以”列“形式导出为JSON数据格式。 我们在整理文档时&#xff0c;产品会通过Excel将功能点和功能描述分层级整理出来&#xff0c;有时需要将此数据导入到系统中&#xff0c;Web端对Json这类数据比较友好&#xff0c;所以这里试着使用E…

实现加盐加密方法以及MappedByteBuffer,RandomAccess

目录 自己实现 Spring Security MappedByteBuffer RandomAccess 加盐加密的实现 自己实现 传统MD5可通过彩虹表暴力破解&#xff0c; 加盐加密算法是一种常用的密码保护方法&#xff0c;它将一个随机字符串&#xff08;盐&#xff09;添加到原始密码中&#xff0c;然后再进…

Java面试题(每天10题)-------连载(46)

目录 Dubbo篇 1、Dubbo的默认集群容错方案 2、Dubbo支持哪些序列化方式&#xff1f; 3、Dubbo超时时间怎样设置&#xff1f; 4、服务调用超时问题怎么解决&#xff1f; 5、Dubbo在安全机制方面是如何解决的&#xff1f; 6、Dubbo和Dubbox之间的区别 7、Dubbo和Spring C…

java--正则表达式用于查找信息、用于搜索替换、分割内容

1.案例&#xff1a;使用正则表达式查找一段文本中的内容 需求&#xff1a;请把下面文本中的电话&#xff0c;邮箱&#xff0c;座机号码&#xff0c;热线都爬取出来。 2.正则表达式用于搜索替换、分割内容&#xff0c;需要结合String提供的如下方法完成

MySQL使用教程

数据构成了我们日益数字化的社会基础。想象一下&#xff0c;从移动应用和银行系统到搜索引擎&#xff0c;再到如 ChatGPT 这样的先进人工智能聊天机器人&#xff0c;这些工具若没有数据支撑&#xff0c;将寸步难行。你有没有好奇过这些海量数据都存放在哪里呢&#xff1f;答案正…

Java程序编写(下)

Scanner对象 通过java.util.Scanner来获得Scanner类 基本语法&#xff1a; Scanner s new Scanner(System.in)通过next()和nextLine()方法获取输入的字符串。 通过hasNext()和hasNextLine()判断是否还有输入的数据。 next(): 1、一定要读取到有效字符后才可以结束输入 2、…

uniapp移动端悬浮按钮(吸附边缘)

Uniapp移动端悬浮按钮可以通过CSS实现吸附边缘的效果。具体实现步骤如下&#xff1a; html&#xff1a; <movable-area class"movable-area"><movable-view class"movable-view" :position"position" :x"x" :y"y"…

列出最佳Aspera替代方案,给你执掌数据传输的权

Aspera是一种高速文件传输技术&#xff0c;广泛应用于科学研究、医疗保健、媒体和娱乐等领域。然而&#xff0c;由于Aspera的高昂价格&#xff0c;很多人不得不寻找替代方案。本文将列举最佳Aspera替代方案&#xff0c;以便执掌数据传输的权利。 1、FileZilla FileZilla是一款…

XUbuntu22.04之8款免费UML工具(一百九十七)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

基于ssm的电动车租赁网站论文

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本电动车租赁网站就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信息&…

FreeSSL申请免费域名证书

本文详细讲解如何申请免费证书&#xff0c;需要先准备好域名&#xff0c;将服务器IP和域名绑定。 1、注册FreeSSL账号 网址&#xff1a; https://freessl.org/ 2、申请流程 登录后首页输入域名&#xff0c;然后点击Create certificate&#xff0c;跳转到证书申请页面。 或者…

LLM中的Prompt提示

简介 在LLM中&#xff0c;prompt&#xff08;提示&#xff09;是一个预先设定的条件&#xff0c;它可以限制模型自由发散&#xff0c;而是围绕提示内容进行展开。输入中添加prompt&#xff0c;可以强制模型关注特定的信息&#xff0c;从而提高模型在特定任务上的表现。 结构 …

Ubuntu安装TensorRT

文章目录 1. 安装CUDAa. 下载CUDAb. 安装CUDAc. 验证CUDA 2. 安装CUDNNa. 下载CUDNNb. 安装CUDNNc. 验证CUDNN 3. 安装TensorRTa. 下载TensorRTb. 解压TensorRTc. 安装TensorRTd. 安装uff和graphsurgeone. 验证是否安装成功f. 备注 关注公众号&#xff1a;『AI学习星球』 回复&…

kafka支持外网访问

kafka支持外网访问 1.kafka正常部署之后如果不修改&#xff0c;外网是无法访问的&#xff0c;具体如下&#xff08;这里是单节点&#xff09; 2.这个时候需要修改kafka的config中的server.properties中的 listeners 修改为0.0.0.0 监控所有网卡&#xff0c;advertised.listene…

硬件开发笔记(十五):RK3568底板电路VGA显示接口原理图分析

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/134849296 红胖子网络科技博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬…

tp5 rewrite nginx重写

tp框架,默认的访问路径是 www.xxxx.com/index.php/admin/shop/index格式的&#xff0c;为了方便和更规范&#xff0c;也看起来有逼格一些&#xff0c;需要将index.php去掉 无index.php就会报404 我这里是宝塔 #地址重写if (!-e $request_filename) {rewrite ^(.*)$ /index.…