Springboot结合redis实现关注推送

news2025/1/16 5:43:27

关注推送

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,用户可以看到其他协作者的实时编辑。 财经应用,实时推送股票价格变动。

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

使用推模式实现关注推送

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

  @Override
    public 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());
            });
        }
        // 返回id
        return 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

具体代码:

  @Override
    public Result queryBlogOfFollow(Long max, Integer offset) {
//        获取用id
        Long userId = UserHolder.getUser().getId();
//       获取关注用户的key
        String key = "feed:" + userId;
//        获取redis里面的推送数据  ZREVRANGEBYSCORE feed:1 当前时间戳 0 WITHSCORES limit 最后一次统计的值 3
        Set<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的id
        List<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查询对应的blog
        List<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.coloradmin.cn/o/1810490.html

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

相关文章

打造精细化运维新玩法(三)

实践SLO&#xff0c;概括下就是在相对标准、统一的框架下指导和推动服务质量的数字化建设&#xff0c;形成对组织有价值的数据资产和流程规范。借用在人工智能和机器学习领域的观点&#xff0c;算法的上限受限于数据质量的好坏&#xff0c;所以从源头上建设高质量的数据非常重要…

【电赛】STM32-PID直流减速电机小车【寻迹+避障+跟随】【更新ing】

一.需求分析 1.主控&#xff1a;STM32C8T6&#xff08;没什么好说的哈哈&#xff09; 2.电机&#xff1a;JAG25-370电机 【问】为什么要用直流减速电机&#xff1f;&#xff1f; PID控制器需要依靠精确的反馈信号来调整其输出&#xff0c;确保电机按照预定的速度和位置运行…

独立游戏之路:Tap篇 -- Unity 集成 TapTap 广告详细步骤

Unity 集成 TapADN 广告详细步骤 前言一、TapTap 广告介绍二、集成 TapTap 广告的步骤2.1 进入广告后台2.2 创建广告计划2.3 选择广告类型三、代码集成3.1 下载SDK3.2 工程配置3.3 源码分享四、常见问题4.1 有展现量没有预估收益 /eCPM 波动大?4.2 新建正式媒体找不到预约游戏…

介绍Linux

目录 1.什么是操作系统 2.现实生活中的操作系统 3.操作系统的发展史 4.操作系统的发展 Linux的不同版本以及应用领域 1.Linux内核及发行版介绍 <1>Linux内核版本 <2>Linux发行版本 2.应用领域 个⼈桌⾯领域的应⽤ 服务器领域 嵌⼊式领域 3.文件和目录 …

HDFS 读写数据流程

优质博文&#xff1a;IT-BLOG-CN 一、HDFS 写数据流程 HDFS 文件写入流程图如下&#xff1a;三个模块&#xff08;客户端、NameNode、DataNode&#xff09; 【1】校验&#xff1a; 客户端通过 DistributedFileSystem 模块向 NameNode 请求上传文件&#xff0c;NameNode 会检…

Vue 面试通杀秘籍

理论篇&#xff1a; 1. 说说对 Vue 渐进式框架的理解&#xff08;腾讯医典&#xff09; a) 渐进式的含义&#xff1a; 主张最少, 没有多做职责之外的事 b) Vue 有些方面是不如 React&#xff0c;不如 Angular.但它是渐进的&#xff0c;没有强主张&#xff0c; 你可以在原有…

Java面向对象-Object类的toString方法、equals方法

Java面向对象-Object类的toString方法、equals方法 一、toString二、equals三、总结 一、toString Object的toString方法。 方法的原理&#xff1a; 现在使用toString方法的时候&#xff0c;打印出来的内容不友好。 现在想要知道对象的信息。 出现的问题&#xff1a;子类Stu…

SAP Build 2 PDF数据提取与决策树(未完成)

0. 安装desktop agent 在后续过程中发现要预先安装desktop agent&#xff0c;否则没法运行自动化流程… 0.1 agent下载 参考官方文档说明 https://help.sap.com/docs/build-process-automation/sap-build-process-automation/create-user-in-rbsc-download-repository?loca…

AI办公自动化:用Kimi批量在Excel文件名中加入日期

工作任务&#xff1a;在一个文件夹中所有的Excel文件后面加上一个日期 在Kimi中输入提示词&#xff1a; 你是一个Python编程专家&#xff0c;写一个Python脚本&#xff0c;具体步骤如下&#xff1a; 打开文件夹&#xff1a;F:\AI自媒体内容\AI行业数据分析\投融资 读取里面所…

18.2 HTTP服务器-处理函数、响应404错误

1. 处理函数 处理来自客户端的请求&#xff0c;并回之以特定的响应&#xff0c;这是处理函数的主要任务。在处理函数中&#xff0c;我们通常会完成如下工作&#xff1a; 验证请求路径 http.Request.URL.Pathhttp.NotFound(...) 当请求没有对应的处理函数时&#xff0c;返回4…

机器学习笔记:label smoothing

在传统的分类任务中&#xff0c;我们通常使用硬标签&#xff08;hard labels&#xff09; 即如果一个样本属于某个类别&#xff0c;其对应的标签就是一个全0的向量&#xff0c;除了表示这个类别的位置为1。例如&#xff0c;在一个3类分类任务中&#xff0c;某个样本的标签可能是…

【Vue】购物车案例-构建项目

脚手架新建项目 (注意&#xff1a;勾选vuex) 版本说明&#xff1a; vue2 vue-router3 vuex3 vue3 vue-router4 vuex4/pinia vue create vue-cart-demo需要勾选上vuex&#xff0c;由于这个项目只有一个页面&#xff0c;vuex可勾可不勾 将原本src内容清空&#xff0c;替换成教学…

缓存更新策略中级总结

背景 看到好些人在写更新缓存数据代码时&#xff0c;先删除缓存&#xff0c;然后再更新数据库&#xff0c;而后续的操作会把数据再装载的缓存中。然而&#xff0c;这个是逻辑是错误的。试想&#xff0c;两个并发操作&#xff0c;一个是更新操作&#xff0c;另一个是查询操作…

数据结构(常见的排序算法)

1.插入排序 1.1直接插入排序 在[0 end]区间上有序&#xff0c;然后将&#xff08;end1&#xff09;的数据与前面有序的数据进行比较&#xff0c;将&#xff08;end1&#xff09;的数据插入&#xff0c;这样[0 end1]区间上就是有序的&#xff0c;然后再向后进行比较。 例如&a…

VXLAN技术

VXLAN技术 一、VXLAN简介 1、定义 VXLAN&#xff08;Virtual eXtensible Local Area Network&#xff09;&#xff1a;采用MAC in UDP&#xff08;User Datagram Protocol&#xff09;封装方式&#xff0c;是NVO3&#xff08;Network Virtualization over Layer 3&#xff09…

机器学习算法 —— 贝叶斯分类之模拟离散数据集

&#x1f31f;欢迎来到 我的博客 —— 探索技术的无限可能&#xff01; &#x1f31f;博客的简介&#xff08;文章目录&#xff09; 目录 实战&#xff08;贝叶斯分类&#xff09;莺尾花数据模拟离散数据集库函数导入数据导入和分析模型训练和预测 总结 实战&#xff08;贝叶斯…

C语言 | Leetcode C语言题解之第144题二叉树的前序遍历

题目&#xff1a; 题解&#xff1a; int* preorderTraversal(struct TreeNode* root, int* returnSize) {int* res malloc(sizeof(int) * 2000);*returnSize 0;if (root NULL) {return res;}struct TreeNode *p1 root, *p2 NULL;while (p1 ! NULL) {p2 p1->left;if (…

一道Delphi的For循环题目

起因 事情是这样的&#xff1a; 俺在一个Delphi交流QQ群&#xff0c;有点冷场&#xff0c;俺想热一下场子就发了下面这个段子。其实这是之前俺带新人时的一道题目。 第一个回答 第一个网友给的答案是 i:i-1; 俺说这个答案是不对的&#xff0c;因为 Delphi在编译时是不允许…

探索智慧机场运营中心解决方案的价值与应用

随着全球航空业的不断发展&#xff0c;机场运营中心的作用日益凸显。智慧机场运营中心解决方案以其高效的管理和智能化的运营模式&#xff0c;成为优化机场运营、提升服务水平的重要工具。本文将深入探讨智慧机场运营中心解决方案的价值与应用&#xff0c;揭示其在机场管理中的…

软件下载网站源码附手机版和图文教程

PHP游戏应用市场APP软件下载平台网站源码手机版 可自行打包APP&#xff0c;带下载统计&#xff0c;带多套模板&#xff0c;带图文教程&#xff0c;可以做软件库&#xff0c;也可以做推广app下载等等&#xff0c;需要的朋友可以下载 源码下载 软件下载网站源码附手机版和图文…