【遇见青山】基于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…...

大气温室气体浓度不断增加,导致气候变暖加剧,随之会引发一系列气象、生态和环境灾害怎样解决?
大气温室气体浓度不断增加,导致气候变暖加剧,随之会引发一系列气象、生态和环境灾害。如何降低温室气体浓度和应对气候变化已成为全球关注的焦点。海洋是地球上最大的“碳库”,“蓝碳”即海洋活动以及海洋生物(特别是红树林、盐沼和海草&…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql
智慧工地管理云平台系统,智慧工地全套源码,java版智慧工地源码,支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求,提供“平台网络终端”的整体解决方案,提供劳务管理、视频管理、智能监测、绿色施工、安全管…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...

使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...
React---day11
14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store: 我们在使用异步的时候理应是要使用中间件的,但是configureStore 已经自动集成了 redux-thunk,注意action里面要返回函数 import { configureS…...