【遇见青山】基于Redis的Feed流实现案例

news2025/2/23 6:05:42

【遇见青山】基于Redis的Feed流实现案例

  • 1.关注推送
  • 2.具体代码实现

1.关注推送

关注推送也叫做Feed流,直译为投喂。为用户持续的提供"沉浸式”的体验,通过无限下拉刷新获取新的信息。

在这里插入图片描述

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

在这里插入图片描述

这里我们实现基本的TimeLine Feed流模式:

TimeLine Feed流模式有三种基本的实现方案:

拉模式:也叫做读扩散🦿

在这里插入图片描述

推模式:也叫做写扩散👣

在这里插入图片描述

推拉结合模式:也叫做读写混合,兼具推和拉两种模式的优点🤺

在这里插入图片描述

Feed流的实现方案分析:

在这里插入图片描述

点评类网站或App,宜使用推模式,短视频类网站或App,宜使用推拉结合模式⛷️


2.具体代码实现

需求分析:

  1. 修改新增探店笔记的业务,在保存blog到数据库的同时,推送到粉丝的收件箱
  2. 收件箱满足可以根据时间戳排序,必须用Redis的数据结构实现
  3. 查询收件箱数据时,可以实现分页查询

分析:实现滚动分页的方式

Feed流中的数据会不断更新,所以数据的角标也在变化,因此不能采用传统的分页模式,而要采用滚动分页,Redis数据结构中终于List和SortedSet支持分页,但List不支持滚动分页功能,所以Redis数据结构我们宜采用SortedSet!

在这里插入图片描述

首先,在保存博客的时候要推送给所有的粉丝(收件箱):

/**
 * 保存博客
 *
 * @param blog 博客对象
 * @return 博客的ID
 */
@Override
public Result saveBlog(Blog blog) {
    // 获取登录用户
    UserDTO user = UserHolder.getUser();
    blog.setUserId(user.getId());
    // 保存探店博文
    boolean isSave = save(blog);
    if (!isSave) {
        return Result.fail("新增笔记失败!");
    }
    // 查询笔记作者的所有粉丝
    List<Follow> follows = followService.query().eq("follow_user_id", user.getId()).list();
    for (Follow follow : follows) {
        Long userId = follow.getUserId();
        // 开始推送
        stringRedisTemplate.opsForZSet().add(FEED_KEY + userId, blog.getId().toString(), System.currentTimeMillis());
    }
    // 返回id
    return Result.ok(blog.getId());
}

实现具体的滚动分页查询:

/**
 * 滚动分页查询Feed流推送的博客
 *
 * @param max    上一次查询的最小值,用于实现滚动查询
 * @param offset 偏移量,防止查询到重复数据
 * @return Result
 */
@Override
public Result queryBlogOfFollow(Long max, Integer offset) {

    // 获取当前用户
    Long userId = UserHolder.getUser().getId();

    // 查询当前用户的收件箱
    Set<ZSetOperations.TypedTuple<String>> tuples = stringRedisTemplate.opsForZSet().
            reverseRangeByScoreWithScores(FEED_KEY + userId, 0, max, offset, DEFAULT_PAGE_SIZE);
    if (tuples == null || tuples.isEmpty()) {
        return Result.ok();
    }

    // 创建集合,保存id
    ArrayList<Long> ids = new ArrayList<>(tuples.size());

    // 保存最小时间
    long minTime = 0;

    // 保存偏移量
    int os = 1;

    // 开始解析数据,得到最终的ids,minTime,offset(os)值
    for (ZSetOperations.TypedTuple<String> tuple : tuples) {
        // 获取id并保存
        ids.add(Long.valueOf(Objects.requireNonNull(tuple.getValue())));
        // 获取分数(时间戳)
        long time = Objects.requireNonNull(tuple.getScore()).longValue();
        if (time == minTime) {
            os++;
        } else {
            // 最后一个元组的时间一定是最小时间
            minTime = time;
            // 重置偏移量
            os = 1;
        }
    }
    String idStr = StrUtil.join(",", ids);
    // 根据id查询blog
    List<Blog> blogs = query().in("id", ids)
            .last("ORDER BY FIELD(id," + idStr + ")").list();

    // 给每个blog封装点赞,作者等信息
    for (Blog blog : blogs) {
        // 查询blog有关的用户
        queryBlogUser(blog);
        // 查询blog的点赞信息,当前用户是否点过赞?
        isBlogLiked(blog);
    }

    // 返回博客集合给前端
    ScrollResult scrollResult = new ScrollResult();
    scrollResult.setList(blogs);
    scrollResult.setMinTime(minTime);
    scrollResult.setOffset(os);
    return Result.ok(scrollResult);
}

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

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

相关文章

Python 爬虫工程师面试经验分享,金三银四

&#x1f643; 作为一个 Python 爬虫工程师&#xff0c;我可以分享一些我在面试中的经验和建议。 首先一点是在面试中要表现自信、友好、乐于合作&#xff0c;同时对公司的业务和文化也要有一定的了解和兴趣&#xff0c;这些也是公司在招聘中看重的因素。 文章目录&#x1f55b…

第06章_MySQL多表查询

第06章_多表查询 讲师&#xff1a;尚硅谷-宋红康&#xff08;江湖人称&#xff1a;康师傅&#xff09; 官网&#xff1a;http://www.atguigu.com 多表查询&#xff0c;也称为关联查询&#xff0c;指两个或更多个表一起完成查询操作。 前提条件&#xff1a;这些一起查询的表之…

node.js基于Vue的英语在线学习网站 vscode+mysql

该系统的基本功能包括管理员、学生、教师三个角色功能模块。 对于管理员可以使用的功能模块主要有首页、个人中心&#xff0c;学生管理、教师管理、班级管理、课程管理&#xff0c;在线学习管理、作业管理、试卷管理、试题管理、 在线论坛、系统管理、考试管理等功能。 对于学生…

STM32F765ZIT6中文规格STM32F765ZGT6引脚图 微控制器MCU

说明STM32F7 32 位 MCUFPU 基于高性能的 ARMCortex-M7 32 位 RISC 内核&#xff0c;工作频率高达 216MHz。Cortex-M7 内核具有单浮点单元(SFPU)精度&#xff0c;支持所有 ARM 单精度数据处理指令与数据类型。同时执行全套 DSP 指令和存储保护单元&#xff08;MPU&#xff09;&a…

各CCF期刊点评网站/学术论坛的信息汇总及个人评价

CCF中文期刊投稿选择之篇章一:各CCF期刊点评网站/学术论坛的信息汇总及个人评价中文科技期刊A类&#xff08;EI检索&#xff09;中文期刊投稿点评网站整理1.小木虫学术论坛2. Letpub3. Justscience4. 发表记5. 会伴&#xff08;Conference Partner)6. ijouranl7. 掌桥科研这是以…

Win11的两个实用技巧系列之如何关闭登录密码?

Win11如何关闭登录密码?Win11关闭登录密码的两种解决方法win11是电脑更新后的全新系统&#xff0c;每次开启需要输入密码。有的用户嫌麻烦想要关闭&#xff0c;下面小编就为大家带来了关闭的方法&#xff0c;一起来看看吧有不少用户在升级或者第一次使用Win11系统的时候&#…

uni-app做微信小程序的分包处理

我们的都知道微信小程序有随即随用&#xff0c;用完即走的优点&#xff0c;并且它开发门槛低&#xff0c;但是它也有一个致命的缺点&#xff0c;就是代码包体积的限制&#xff0c;这一缺点让小程序的开发有了一定的限制&#xff0c;现在有一方法可以减少代码包的体积&#xff0…

界面组件Telerik ThemeBuilder R1 2023开创应用主题研发新方式!

Telerik DevCraft包含一个完整的产品栈来构建您下一个Web、移动和桌面应用程序。它使用HTML和每个.NET平台的UI库&#xff0c;加快开发速度。Telerik DevCraft提供最完整的工具箱&#xff0c;用于构建现代和面向未来的业务应用程序&#xff0c;目前提供UI for ASP.NET包含一个完…

汉诺塔递归算法精讲

文章目录前言一、汉诺塔是个啥&#xff1f;二、手动解法三、解法抽象四、递归解法五、总结前言 递归算法是计算机算法中的基础算法&#xff0c;也是非常重要的算法&#xff0c;从某种程度上讲&#xff0c;它有一点儿AI的影子。人脑是可以完成递归思路的&#xff0c;但是对不起…

《爆肝整理》保姆级系列教程python接口自动化(十五)--参数关联接口(详解)

简介 我们用自动化新建任务之后&#xff0c;要想接着对这个新建任务操作&#xff0c;那就需要用参数关联了&#xff0c;新建任务之后会有一个任务的Jenkins-Crumb&#xff0c;获取到这个Jenkins-Crumb&#xff0c;就可以通过传这个任务Jenkins-Crumb继续操作这个新建的任务。 …

自适应布局之淘宝无限适配+rem+微信rpx自适应

一、自适应布局 所谓前端适配&#xff0c;就是为了让移动设计稿在大部分的移动设备上看起来有一致的展示效果&#xff0c;目前比较流行的方法有两种。一种是强制meta viewport宽度为设计稿宽度&#xff0c;一种是使用rem自适应布局的flexible.js。 二、当前流行的移动端自适应…

【刷题笔记】--盛最多水的容器--双指针

题目&#xff1a; 给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xff0c;第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线&#xff0c;使得它们与 x 轴共同构成的容器可以容纳最多的水。 返回容器可以储存的最大水量。 说明&#xff1a;你不…

Python 高级编程之正则表达式(八)

文章目录一、概述二、正则表达式语法1&#xff09;字符匹配2&#xff09;字符集合3&#xff09;定位符4&#xff09;分组1、定义分组2、引用分组3、命名分组三、Python 的 re 模块1&#xff09;re.match() 方法2&#xff09;re.search() 方法3&#xff09;re.match() 与 re.sea…

2023最牛教程,手把手教你成为年薪30W的测试开发

随着互联网行业的高速发展&#xff0c;快速高质量的产品版本迭代成为企业始终立于不败之地的迫切需求&#xff0c;而在短期迭代的快节奏中&#xff0c;传统测试工作面对更大压力&#xff0c;无法持续提供高效率高质量的人力支撑&#xff0c;所以越来越多的企业需要技术更为全面…

Leetcode-每日一题1250. 检查「好数组」(裴蜀定理)

题目链接&#xff1a;https://leetcode.cn/problems/check-if-it-is-a-good-array/description/ 思路 方法&#xff1a;数论 题目意思很简单&#xff0c;让你在数组 nums中选取一些子集&#xff0c;可以不连续&#xff0c;子集中的每个数再乘以任意的数的和是否为1&#xff…

netty

Netty的介绍Netty是异步的&#xff08;指定回调处理&#xff09;、基于事件驱动的网络应用框架&#xff0c;用于快速开发高性能、高可靠性的网络IO程序。Netty本质是一个NIO框架&#xff0c;适用于服务器通讯相关的多种应用场景&#xff0c;分布式节点远程调用中Netty往往作为R…

RTT 消息邮箱

1.邮箱概念 邮箱服务是实时操作系统中一种典型的线程间通信方法。举一个简单的例子&#xff0c;有两个线程&#xff0c;线程 1 检测按键状态并发送&#xff0c;线程 2 读取按键状态并根据按键的状态相应地改变 LED 的亮灭。这里就可以使用邮箱的方式进行通信&#xff0c;线程 …

SpringCloud保姆级搭建教程五---Redis

首先&#xff0c;这个和微服务没有直接的关系&#xff0c;只是在代码开发当中要使用的一个工具而已&#xff0c;为了提高这个系统的性能&#xff0c;加快查询效率等方面而使用它1、首先&#xff0c;要先安装redis到电脑上&#xff0c;这里依然是在windows上演示&#xff0c;之后…

window11, WSL, Ubuntu 20.04 编译TensorRT源码并且安装 TensorRT

一、安装参考 1.ubuntu18.04TensorRT 配置攻略 ubuntu18.04TensorRT 配置攻略 - 简书卷积网络的量化和部署是重要环节&#xff0c;以前我们训练好模型后直接trace进行调用&#xff0c;参考&#xff08;C windows调用ubuntu训练的PyTorch模型&#xff08;.pt/.pth&#xff09;…

Utkuici:一款功能强大的Nessus自动化任务实现工具

关于Utkuici 今天&#xff0c;随着信息技术系统的普及&#xff0c;网络安全领域的投资已大幅增加。各种规模的组织都需要进行漏洞管理、渗透测试和各种分析&#xff0c;以准确确定各自机构受网络威胁的影响程度。通过借助漏洞管理工具的行业领先者Tenable Nessus&#xff0c;我…