Springboot结合redis实现关注推送

关注推送

Feed流的模式

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

优点:信息全面,不会有缺失。并且实现也相对简单 缺点:信息噪音较多,用户不一定感兴趣,内容获取效率低

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

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

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

Timeline里面又有三种模式: 1.拉模式

2.推模式

3.推拉模式

拉模式

Timeline的拉模式(Pull Mode)通常指的是用户端主动请求更新的方式来获取最新动态的一种机制。在社交媒体、问答网站或任何有实时更新内容的应用中,拉模式的工作方式如下:

用户行为:

用户打开应用或刷新页面。 用户选择查看特定用户的动态或时间线。 用户手动下拉刷新(Pull-to-Refresh)来获取新内容。

服务器响应: 服务器接收到用户发起的请求。 根据请求,服务器查询数据库或缓存(如Redis)以获取最新动态。 如果有新的动态,服务器将这些内容发送回客户端。 如果没有新内容,服务器可能返回一个空响应或告知客户端当前无更新。

客户端显示: 客户端接收到新数据后,更新UI显示最新的动态。 如果没有新内容,UI可能会显示一条提示,告诉用户当前内容是最新的。

拉模式的优点包括: 资源效率:只在用户需要时才加载新数据,减少了不必要的网络传输和服务器负载。 控制权:用户可以选择何时获取新信息,提供了更好的用户体验。

缺点则包括: 延迟:用户必须主动操作才能获取新内容,可能会错过实时发生的事件。 频繁请求:如果用户频繁刷新,可能会增加服务器压力和网络流量。 在实际应用中,为了平衡实时性和效率,通常会结合推模式(Push Mode)来实现,比如使用WebSocket或其他长连接技术,当有新动态时服务器可以直接推送给在线用户,而离线用户则可以通过拉模式来获取信息。

推模式

推模式(Push Mode)是一种数据更新机制,其中服务器主动将新数据推送到客户端,而不是等待客户端发起请求。这种方式常用于实时性要求较高的场景,例如即时消息、股票行情、在线协作工具等。以下是推模式的详细描述: 服务器推送: 当服务器上有新的、相关或重要的数据可用时,它会主动将这些数据发送到已连接的客户端。

连接建立: 客户端通常通过持久连接(如WebSocket、Server-Sent Events (SSE) 或其他长连接技术)与服务器保持通信。

实时性: 由于数据是实时推送的,用户可以立即看到更新,无需手动刷新或等待请求响应。

数据传输: 服务器在有新数据时直接通过连接发送,客户端收到数据后立即处理并更新UI。

性能与资源: 推模式可能增加服务器的负载,因为它需要持续监控数据变化并主动推送。 对于客户端,持续的连接可能会消耗更多的电池和网络资源。

用户体验: 提供更好的实时体验,用户可以在数据发生变化时立即得到通知。 可能导致用户设备资源的持续消耗,尤其是对于移动设备。

应用场景: 即时通讯应用,如微信、Slack,服务器会将新消息直接推送给用户。 在线协作工具,如Google Docs,用户可以看到其他协作者的实时编辑。 财经应用,实时推送股票价格变动。

优化与配合: 通常与拉模式结合使用,以平衡实时性和资源消耗。例如,当连接断开时,可以切换到拉模式来获取丢失的数据。 使用推送订阅模型,允许用户仅订阅他们感兴趣的数据。 推模式适合需要实时同步和快速反馈的场景,但需要注意服务器资源和客户端性能的平衡。在设计系统时,通常需要权衡实时性、效率和用户体验。

使用推模式实现关注推送

我们在发布时,查询数据库对应的的粉丝进行推送。

  @Overridepublic Result saveBlog(Blog blog) {// 获取登录用户UserDTO user = UserHolder.getUser();blog.setUserId(user.getId());// 保存探店博文boolean isSuccess = blogService.save(blog);if (!isSuccess){return Result.fail("新增笔记失败");}//查询被关注List<Follow> follows = followService.query().eq("follow_user_id", user.getId()).list();if (!follows.isEmpty()) {follows.forEach(follow -> {//推送给粉丝String key = "feed:" + follow.getUserId();stringRedisTemplate.opsForZSet().add(key, blog.getId().toString(), System.currentTimeMillis());});}// 返回idreturn Result.ok(blog.getId());}

关注推送滚动分页

该功能主要使用sortSet里面的分数机制

ZREVRANGEBYSCORE feed:1 100000 0 WITHSCORES limit 0 3
# feed:1 为键
# 最大值 100000
# 最小值 0
# WITHSCORES 是否全部展示key和value
# 0 偏移量
# 3 条数

通过上面指令我们可分析出对应的参数:

参数
max :第一次使用当前时间戳 | 第二次上一次查询最小的时间戳
min:0
offset :第一次使用0 | 第二次在上一次结果中,与最小值一样的元素的个数
count:3

具体代码:

  @Overridepublic Result queryBlogOfFollow(Long max, Integer offset) {
//        获取用idLong userId = UserHolder.getUser().getId();
//       获取关注用户的keyString key = "feed:" + userId;
//        获取redis里面的推送数据  ZREVRANGEBYSCORE feed:1 当前时间戳 0 WITHSCORES limit 最后一次统计的值 3Set<ZSetOperations.TypedTuple<String>> typedTuples = stringRedisTemplate.opsForZSet().reverseRangeByScoreWithScores(key, 0, max, offset, 2);//判断是否为空if (ObjectUtil.isNull(typedTuples)||typedTuples.isEmpty()){return Result.ok();}long minTime=0;int count=0;
//        创建list存储blog的idList<Long> ids = new ArrayList<>(typedTuples.size());for (ZSetOperations.TypedTuple<String> typedTuple : typedTuples) {ids.add(Long.valueOf(typedTuple.getValue()));long time = typedTuple.getScore().longValue();if (time == minTime) {count++;} else {
//            应因为sortSet是有序的所以最后一个及是最小的minTime = time;count = 1;}}String strIds = StringUtil.join(ids, ",");
//        更具id查询对应的blogList<Blog> blogs = blogService.query().in("id", ids).last("ORDER BY FIELD(id," + strIds + ")").list();
//      设置博客点赞for (Blog blog : blogs) {extracted(blog);setBlogLiked(blog);}
//        返回封装数据ScrollResult scrollResult = new ScrollResult();scrollResult.setList(blogs);scrollResult.setOffset(count);scrollResult.setMinTime(minTime);return Result.ok(scrollResult);}

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

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

相关文章

佳能5DMARK IV mov视频覆盖的恢复方法

5DMARK IV算是佳能比较经典的一款摄像机&#xff0c;是佳能早期使用MOV的摄像机之一&#xff0c;MOV是当初佳能高端机的象征&#xff0c;当然现在佳能已经不在通过MOV和MP4来区分硬件级别了。下边这个案例是文件拍摄时断电&#xff0c;结果变成0字节&#xff0c;然后覆盖了部分…

速度位置规划实现精确定位的问题

&#x1f3c6;本文收录于「Bug调优」专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&&…

论文略读:Onthe Expressivity Role of LayerNorm in Transformers’ Attention

ACL 2023 研究了LayerNorm在 Transformers 中对注意力的作用LayerNorm为Transformer的Attention提供了两个重要的功能&#xff1a; 投影&#xff0c;projection LayerNorm 帮助 Attention 设计一个注意力查询&#xff0c;这样所有的Key都可以平等地访问通过将Key向量投影到同一…

端午节到了,祝大家粽子甜甜,生活美满!愿粉丝们心想事成,健康平安,阖家幸福!

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

【Java基础】多线程开发

Java多线程编程学习笔记 Author: Jim.kk Video: Bilibili 文章目录 Java多线程编程学习笔记学习路线简介程序、进程与线程的关系JVM简介 | 多线程在JVM中的执行示例CPU 线程的调度方式多线程的意义并行与并发 创建多线程 1 | Thread 与 Runnable方式 1 | 继承 Thread 类方式 …

企业网站策划

企业网站策划是企业推广和宣传的重要组成部分&#xff0c;它不仅是企业对外传达形象和信息的平台&#xff0c;更是企业与客户、供应商、合作伙伴进行交流和互动的重要工具。好的企业网站策划不仅能够展示企业形象和产品信息&#xff0c;还能够为用户提供更好的体验&#xff0c;…

Java:集合框架

1.Collection接口 collection接口是Java最基本的集合接口&#xff0c;它定义了一组允许重复的对象。它虽然不能直接创建实例&#xff0c;但是它派生了两个字接口List和Set&#xff0c;可以使用子接口的实现类创建实例。Collection 接口是抽取List接口和Set接口共同的存储特点和…

九种mfc140u.dll丢失的解决方法,全面解决mfc140u.dll文件丢失

mfc140u.dll是 Microsoft Visual C 2015 Redistributable 的一部分&#xff0c;它与 Microsoft 基础类库&#xff08;MFC&#xff09;的 Unicode 版本有关。当您在运行使用 Visual C 2015 开发的应用程序时&#xff0c;可能会碰到关于mfc140u.dll丢失的错误。下面列出了一些解决…

刷机维修进阶教程-----红米k30 nv损坏故障 修复实例教程步骤解析

小米红米系列机型在米8起始就有了串码校验。不得随意更改参数限制。不同于其他机型,可以任意刷入同芯片的基带qcn来修复基带和串码丢失。米系列刷入同芯片基带qcn会提示nv损坏故障。是因为有串码校验。一般在于格机或者全檫除分区后写新参数出现的故障。 这种解决方法通常有两…

Nginx+Tomcat负载均衡,动静分离群集

Nginx反向代理原理 Nginx 反向代理&#xff1a;将Nginx接收到的请求转发给其它应用服务器处理 Nginx 负载均衡&#xff1a;通过反向代理实现&#xff0c;还可以将nginx接收到的请求转发给多个后端应用服务器处理 Nginx 动静分离&#xff1a;静态页面请求&#xff0c;由nginx…

上汽集团25届暑期实习测评校招笔试题库已发(真题)

&#x1f4e3;上汽集团 25届暑期实习测评已发&#xff0c;正在申请的小伙伴看过来哦&#x1f440; ㊙️本次实习项目面向2025届国内外毕业生&#xff0c;开放了新媒体运营、销售策略、市场运营、物流、质量分析等岗位~ ✅测评讲解&#xff1a; &#x1f449;测评自收到起需在…

Linux---防火墙

文章目录 目录 文章目录 前言 一.静态防火墙&#xff1a;iptables iptables五链 iptables 四表 iptables控制类型 iptables命令配置 前言 这儿主要介绍Linux系统本身提供的软件防火墙的功能&#xff0c;即数据包过滤机制。 数据包过滤&#xff0c;也就是分析进入主机的网络数…

cve_2022_0543-redis沙盒漏洞复现 vulfocus

1. 原理 该漏洞的存在是因为Debian/Ubuntu中的Lua库是作为动态库提供的。自动填充了一个package变量&#xff0c;该变量又允许访问任意 Lua 功能。 2.复现 我们可以尝试payload&#xff1a; eval local io_l package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so…

DeepSpeed MoE

MoE概念 模型参数增加很多&#xff1b;计算量没有增加&#xff08;gating小FNN&#xff0c;比以前的大FNN计算量要小&#xff09;&#xff1b;收敛速度变快&#xff1b; 效果&#xff1a;PR-MoE > 普通MoE > DenseTransformer MoE模型&#xff0c;可视为Sparse Model&…

表的设计与查询

目录 一、表的设计 1.第一范式&#xff08;一对一&#xff09; 定义&#xff1a; 示例&#xff1a; 2.第二范式&#xff08;一对多&#xff09; 定义&#xff1a; 要求&#xff1a; 示例&#xff1a; 3.第三范式&#xff08;多对多&#xff09; 定义&#xff1a; 要求…

**《Linux/Unix系统编程手册》读书笔记24章**

D 24章 进程的创建 425 24.1 fork()、exit()、wait()以及execve()的简介 425 . 系统调用fork()允许父进程创建子进程 . 库函数exit(status)终止进程&#xff0c;将进程占用的所有资源归还内核&#xff0c;交其进行再次分配。库函数exit()位于系统调用_exit()之上。在调用fo…

ffmpeg常见命令

一、ffmpeg的安装 ffmpeg的安装 一、ffmpeg常用命令 二、ffprobe

浅解Reids持久化

Reids持久化 RDB redis的存储方式&#xff1a; rdb文件都是二进制&#xff0c;很小&#xff0c;里面存的是数据 实现方式 redis-cli链接到redis服务端 使用save命令 注&#xff1a;不推荐 因为save命令是直接写到磁盘里面&#xff0c;速度特别慢&#xff0c;一般都是redis…

遗传算法笔记:基本工作流程

1 介绍 遗传算法有5个主要任务&#xff0c;直到找到最终的解决方案 2 举例 2.1 问题描述 比如我们有 5 个变量和约束&#xff0c;其中 X1、X2、X3、X4 和 X5 是非负整数且小于 10&#xff08;0、1、2、4、5、6、7、8、9&#xff09;我们希望找到 X1、X2、X3、X4 和 X5 的最…

go语言后端开发学习(三)——基于validator包实现接口校验

前言 在我们开发模块的时候,有一个问题是我们必须要去考虑的&#xff0c;它就是如何进行入参校验&#xff0c;在gin框架的博客中我就介绍过一些常见的参数校验&#xff0c;大家可以参考gin框架学习笔记(四) ——参数绑定与参数验证&#xff0c;而这个其实也不是能够完全应对我…