【遇见青山】基于Redis的Feed流实现案例
【遇见青山】基于Redis的Feed流实现案例
- 1.关注推送
- 2.具体代码实现
1.关注推送
关注推送也叫做Feed流,直译为投喂。为用户持续的提供"沉浸式”的体验,通过无限下拉刷新获取新的信息。

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

这里我们实现基本的TimeLine Feed流模式:
的TimeLine Feed流模式有三种基本的实现方案:
拉模式:也叫做读扩散🦿

推模式:也叫做写扩散👣

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

Feed流的实现方案分析:

点评类网站或App,宜使用推模式,短视频类网站或App,宜使用推拉结合模式⛷️
2.具体代码实现
需求分析:
- 修改新增探店笔记的业务,在保存blog到数据库的同时,推送到粉丝的收件箱
- 收件箱满足可以根据时间戳排序,必须用Redis的数据结构实现
- 查询收件箱数据时,可以实现分页查询
分析:实现滚动分页的方式
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());}// 返回idreturn 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();}// 创建集合,保存idArrayList<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查询blogList<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);
}
相关文章:
【遇见青山】基于Redis的Feed流实现案例
【遇见青山】基于Redis的Feed流实现案例1.关注推送2.具体代码实现1.关注推送 关注推送也叫做Feed流,直译为投喂。为用户持续的提供"沉浸式”的体验,通过无限下拉刷新获取新的信息。 Feed流产品有两种常见模式: 这里我们实现基本的TimeL…...
【芯片前端】一文搞定|寄存器组织生成与uvm ral_model环境全流程
前言 本文以组织一个系统(或模块)寄存器为例,进行寄存器与ral生成相关的全流程展示。内容包括如下几个部分: 寄存器文档组织 描述文件与辅助RTL代码结构 ralf/ral/rtl文件代码结构 UVM RAL访问环境组织 寄存器文档组织 在windows路径下组织寄存器文档,格式为excel表格。…...
Leetcode力扣秋招刷题路-0061
从0开始的秋招刷题路,记录下所刷每道题的题解,帮助自己回顾总结 61. 旋转链表 给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置。 示例 1: 输入:head [1,2,3,4,5], k 2 输出&…...
xilinx srio ip学习笔记之axistream接口
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 xilinx srio ip学习笔记之axistream接口前言接口转化前言 srio 的IQ接口都是基于axistream的,以前没怎么用过axistream的接口,或者说没怎么用过复杂条…...
轨迹误差评估指标[APE/RPE]和EVO
轨迹误差评估指标[APE/RPE]和EVO1. ATE/APE2. RPE3. EVO3.1 评估指标3.2 使用3.2.1 轨迹可视化3.2.2 APE3.2.3 RPEReference: 高翔,张涛 《视觉SLAM十四讲》视觉SLAM基础:算法精度评价指标(ATE、RPE) 在实际工程中,我…...
uni-app 消息推送功能UniPush
uni-app 消息推送功能UniPush,这里用的是uni-app自带的UniPush1.0(个推服务),所以只针对UniPush1.0介绍实现步骤。 建议查阅的文章: UniPush 1.0 使用指南[2] Unipush 常见问题[3] 当然现在已经出了UniPush2.0(HBuilde…...
面试题(二十六)场景应用
1. 场景应用 1.1 微信红包相关问题 参考答案 概况:2014年微信红包使用数据库硬抗整个流量,2015年使用cache抗流量。 微信的金额什么时候算? 微信红包的金额是拆的时候实时算出来,不是预先分配的,采用的是纯内存计…...
密码技术在车联网安全中的应用与挑战
随着智慧交通和无人驾驶的快速发展,车联网产业呈现蓬勃发展态势,车与云、车与车、车与路、车与人等综合网络链接的融合程度越来越高,随之而来的安全挑战也更加严峻。解决车联网的安全问题需要一个整体的防护体系,而密码技术凭借技…...
富媒体数据管理解决方案:简化、优化、自动化
富媒体数据管理解决方案:简化、优化、自动化 适用于富媒体的 NetApp 解决方案有助于简化和降低数据管理成本,优化全球媒体工作流并自动执行媒体资产管理。这将有助于减轻您的负担。 为什么选择 NetApp 的富媒体数据管理解决方案? 成本更低…...
QT入门Input Widgets之QFontComboBox、QTextEdit、QPlainTextEdit、QDial、QKeySequenceEdit
目录 一、QFontComboBox的相关介绍 1、实际使用 二、QTextEdit与QPlainTextEdit 三、QDial的相关介绍 四、QKeySequenceEdit的相关介绍 此文为作者原创,创作不易,转载请标明出处! 一、QFontComboBox的相关介绍 1、实际使用 一般使用较…...
Java企业级开发学习笔记
文章目录一、Spring1.1、Slay Dragon1.2、RescueDamselQuest一、Spring 第一周写了两个小项目均使用了原始调用和容器的方法 两个项目:<斩杀大龙与上路保卫战> 配一张文件位置图 1.1、Slay Dragon BraveKnight package net.sherry.spring.day01;public c…...
【算法基础】(一)基础算法 ---高精度
✨个人主页:bit me ✨当前专栏:算法基础 🔥专栏简介:该专栏主要更新一些基础算法题,有参加蓝桥杯等算法题竞赛或者正在刷题的铁汁们可以关注一下,互相监督打卡学习 🌹 🌹 dz…...
电源口防雷器电路设计方案
电源口防雷电路的设计需要注意的因素较多,有如下几方面:1、防雷电路的设计应满足规定的防护等级要求,且防雷电路的残压水平应能够保护后级电路免受损坏。2、在遇到雷电暂态过电压作用时,保护装置应具有足够快的动作响应速度&#…...
【零基础入门前端系列】—表单(七)
【零基础入门前端系列】—表单(七) 一、什么是表单 表单在Web网页中用来给访问者填写信息,从而采集客户信息端,使得网页具有交互功能。一般是将表单设计在一个HTML文档中,当用户填写完信息后做提交操作,于…...
Linux安装python3
Linux安装python3一.介绍二.下载三.配置1.文件夹2.安装依赖3.安装4.配置4.1python关系4.2配置测试-映射python3文件4.2.1 不用设置默认python3为默认版本4.2.2 将python3设置默认版本一.介绍 因为我的Centos7虚拟机里面只有python2.7.5,我想安装一个python3但是还要…...
怎么通过中级职称有窍门吗?
中级职称评审对人才加薪、升职自然不必说,更重要的是职称证书对于公司和企业同样具有重要的价值和意义,因此只要是说公司办理资质或者有项目招投标的公司对于人才参加中级职称评审毫无疑问会给予大力支持,既然工程师职称有这么多的好处&#…...
SAP ABAP根据事务码查找增强最直接的方法
下面是为任意事务代码查找用户出口的步骤: 方法一: 第 1 步:使用 事务代码:SE93。输入您要搜索用户出口的 事务代码。 在我们的场景中,我们将使用 CO11N。 第 2 步:点击显示: 第 3 步…...
HTTP协议——详细讲解
目录 一、HTTP协议 1.http 2.url url的组成: url的保留字符: 3.http协议格式编辑 ①http request ②http response 4.对request做出响应 5.GET与POST方法 ①GET ②POST 7.HTTP常见Header ①Content-Type:: 数据类型(text/html等)在上文…...
echonet-dynamic代码解读
1 综述 一共是这些代码,我们主要看echo.py,segmentation.py,video.py,config.py。 2 配置文件config.py 基于配置文件设置路径。 """Sets paths based on configuration files."""import conf…...
大气温室气体浓度不断增加,导致气候变暖加剧,随之会引发一系列气象、生态和环境灾害怎样解决?
大气温室气体浓度不断增加,导致气候变暖加剧,随之会引发一系列气象、生态和环境灾害。如何降低温室气体浓度和应对气候变化已成为全球关注的焦点。海洋是地球上最大的“碳库”,“蓝碳”即海洋活动以及海洋生物(特别是红树林、盐沼和海草&…...
[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解
突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 安全措施依赖问题 GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...
VB.net复制Ntag213卡写入UID
本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...
【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...
基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...
ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
React---day11
14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store: 我们在使用异步的时候理应是要使用中间件的,但是configureStore 已经自动集成了 redux-thunk,注意action里面要返回函数 import { configureS…...
JS设计模式(4):观察者模式
JS设计模式(4):观察者模式 一、引入 在开发中,我们经常会遇到这样的场景:一个对象的状态变化需要自动通知其他对象,比如: 电商平台中,商品库存变化时需要通知所有订阅该商品的用户;新闻网站中࿰…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...
day36-多路IO复用
一、基本概念 (服务器多客户端模型) 定义:单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用:应用程序通常需要处理来自多条事件流中的事件,比如我现在用的电脑,需要同时处理键盘鼠标…...
