基于Redis实现关注、取关、共同关注及消息推送(含源码)

微信公众号访问地址:基于Redis实现关注、取关、共同关注及消息推送(含源码)

推荐文章:

    1、springBoot对接kafka,批量、并发、异步获取消息,并动态、批量插入库表;

    2、SpringBoot用线程池ThreadPoolTaskExecutor异步处理百万级数据;

    3、为什么引入Redisson分布式锁?

    4、Redisson可重入锁原理

    5、SpringBoot整合多数据源,并支持动态新增与切换(详细教程)

一、简介

       实现用户之间的关注和取消关注、查询是否关注、共同关注及关注后消息采用feed方式推送及滚动分页查看效果等相关功能。利用redis里面的Set集合实现关注,取关,共同关注,消息推送等,结合Java代码实现具体的功能。

二、实现关注和取关

2.1、关注和取消关注功能

业务流程图:

核心代码实现:

public Result follow(Long followUserId, Boolean isFollow,Long userId) {// 1.获取登录用户 暂时先缓存前端传用户ID
//        Long userId = UserHolder.getUser().getId();String key = "follows:" + userId;// 1.判断到底是关注还是取关if (isFollow) {// 2.关注,新增数据Follow follow = new Follow();follow.setUserId(userId);  //当前登录人员IDfollow.setFollowUserId(followUserId);  //关注用户的idboolean isSuccess = save(follow);if (isSuccess) {// 把关注用户的id,放入redis的set集合 sadd userId followerUserIdstringRedisTemplate.opsForSet().add(key, followUserId.toString());}} else {// 3.取关,删除 delete from tb_follow where user_id = ? and follow_user_id = ?boolean isSuccess = remove(new QueryWrapper<Follow>().eq("user_id", userId).eq("follow_user_id", followUserId));if (isSuccess) {// 把关注用户的id从Redis集合中移除stringRedisTemplate.opsForSet().remove(key, followUserId.toString());}}return Result.ok();}
 

结果展示:

2.2、共同关注功能

2.3、使用的redis命令如下:

SINTER key1 [key2]返回给定所有集合的交集

2.4、代码实现

public Result followCommons(Long id,Long userId) {// 1.获取当前用户
//        Long userId = UserHolder.getUser().getId();String key = "follows:" + userId;// 2.求交集String key2 = "follows:" + id;Set<String> intersect = stringRedisTemplate.opsForSet().intersect(key, key2);if (intersect == null || intersect.isEmpty()) {// 无交集return Result.ok(Collections.emptyList());}// 3.解析id集合List<Long> ids = intersect.stream().map(Long::valueOf).collect(Collectors.toList());// 4.查询用户List<UserDTO> users = userService.listByIds(ids).stream().map(user -> BeanUtil.copyProperties(user, UserDTO.class)).collect(Collectors.toList());return Result.ok(users);}

2.5、结果展示

三、关注推送

3.1、Feed流模式

3.2、常见模式

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

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

    >优点:信息全面,不会有缺失。并且实现也相对简单。

    >缺点:信息噪音较多,用户不一定感兴趣,内容获取效率低。

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

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

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

     本例中的个人页面,是基于关注的好友来做Feed流,因此采用Timeline的模式。该模式的实现方案有三种:

①拉模式   ②推模式    ③推拉结合

3.3、三种实现方案

3.3.1、拉模式

说明:粉丝主动去拉取相关信息。

3.3.2、推模式

说明:博主主动推送相关信息给粉丝。

3.3.3、推拉结合模式

说明活跃粉丝:博主主动推送相关信息给粉丝。普通粉丝:粉丝主动去拉取相关信息。

3.3.4、总结

       对于大部分中小型公司需求,采取推模式基本上满足需求,对于超千万的用户量的大型公司,需要采取推拉模式,但是实现上相比就复杂多了。

四、案例

4.1、需求分析

滚动分页:

4.2、使用到的redis命令

1、ZREVRANGEBYSCORE:Redis的一个Sorted Set命令,用于按照分数从高到低的顺序返回满足指定分数范围条件的元素。它的语法如下:

ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count]

参数解释如下:

    key:排序集合的键名。

    max:分数范围的上限,可以使用"+inf"表示正无穷大。

    min:分数范围的下限,可以使用"-inf"表示负无穷大。

    WITHSCORES:可选参数,表示返回结果时同时返回元素与分数。

    LIMIT:可选参数,用于限制返回结果的偏移量和数量。

示例用法:

ZREVRANGEBYSCORE myset 100 0ZREVRANGEBYSCORE myset (100 0 WITHSCORESZREVRANGEBYSCORE myset 100 0 LIMIT 0 10

第一个示例命令将返回分数从最高到最低的所有元素,分数范围为(100,0],不包括100。

第二个示例命令将返回分数从最高到最低的所有元素及其对应的分数,分数范围为(100,0],不包括100。

第三个示例命令将返回分数从最高到最低的前10个元素,分数范围为(100,0],不包括100。

注意:ZREVRANGEBYSCORE是按照分数从高到低的顺序返回结果的,如果需要按照分数从低到高的顺序返回结果,可以使用ZRANGEBYSCORE命令。

2、ZADD:在Redis中,ZADD命令用于向有序集合(Sorted Set)中添加一个或多个成员。有序集合是一种将成员与分数(score)关联的数据结构,通过分数可以对成员进行排序。

ZADD命令的语法如下:

ZADD key [NX|XX] [CH] [INCR] score member [score member ...]

参数说明:

    key:有序集合的键名。

    NX:仅在键不存在时添加成员。

    XX:仅在键已经存在时添加成员。

    CH:返回修改的成员数量,包括新增和更新的成员。

    INCR:对已经存在的成员的分数进行自增操作。

    score:成员的分数,用于排序。

    member:要添加的成员。

示例:

ZADD myset 1 "member1"ZADD myset 2 "member2" 3 "member3"

注意:ZADD命令在Redis版本2.4以及以上版本可用。

reids中实现滚动分页功能:

4.3、业务流程图

4.4、核心代码展示

4.4.1、保存探店笔记并发送收件箱

  public Result saveBlog(Blog blog) {Long userId = 999L;  //暂时写死// 1.获取登录用户
//        UserDTO user = UserHolder.getUser();
//        blog.setUserId(user.getId());blog.setUserId(userId);// 2.保存探店笔记boolean isSuccess = save(blog);if(!isSuccess){return Result.fail("新增笔记失败!");}// 3.查询笔记作者的所有粉丝 select * from tb_follow where follow_user_id = ?List<Follow> follows = followService.query().eq("follow_user_id", userId).list();//非空判断if(CollUtil.isEmpty(follows)){return Result.ok();}// 4.推送笔记id给所有粉丝for (Follow follow : follows) {// 4.1.获取粉丝idLong uId = follow.getUserId();// 4.2.feed推送消息String key = FEED_KEY + uId;stringRedisTemplate.opsForZSet().add(key, blog.getId().toString(), System.currentTimeMillis());}// 5.返回idreturn Result.ok(blog.getId());}

4.4.2、查询关注的所有探店笔记(并含滚动分页)

public Result queryBlogOfFollow(Long max, Integer offset) {// 1.获取当前用户
//        Long userId = UserHolder.getUser().getId();Long userId = 111L;// 2.查询收件箱 ZREVRANGEBYSCORE key Max Min LIMIT offset countString key = FEED_KEY + userId;Set<ZSetOperations.TypedTuple<String>> typedTuples = stringRedisTemplate.opsForZSet().reverseRangeByScoreWithScores(key, 0, max, offset, 2);// 3.非空判断if (typedTuples == null || typedTuples.isEmpty()) {return Result.ok();}// 4.解析数据:blogId、minTime(时间戳)、offsetList<Long> ids = new ArrayList<>(typedTuples.size());long minTime = 0; // 2int os = 1; // 2for (ZSetOperations.TypedTuple<String> tuple : typedTuples) { // 5 4 4 2 2// 4.1.获取idids.add(Long.valueOf(tuple.getValue()));// 4.2.获取分数(时间戳)long time = tuple.getScore().longValue();if(time == minTime){os++;}else{minTime = time;os = 1;}}// 5.根据id查询blogString idStr = StrUtil.join(",", ids);List<Blog> blogs = query().in("id", ids).last("ORDER BY FIELD(id," + idStr + ")").list();for (Blog blog : blogs) {// 5.1.查询blog有关的用户queryBlogUser(blog);// 5.2.查询blog是否被点赞isBlogLiked(blog);}// 6.封装并返回ScrollResult r = new ScrollResult();r.setList(blogs);r.setOffset(os);r.setMinTime(minTime);return Result.ok(r);}

备注:

4.4.3、请求参数

参考案例:

{  "comments": 0,  "content": "生活就是一半烟火·一半诗意",  "createTime": "2023-08-17T05:17:34.287Z",  "id": 90,  "images": "111111",  "liked": 0,  "name": "11111",  "shopId": 10,  "title": "生活就是一半烟火",  "updateTime": "2023-08-17T05:17:34.287Z",  "userId": 999}

五、源码获取方式

     更多优秀文章,请关注个人微信公众号或搜索“程序猿小杨”查阅。然后回复:源码,可以获取该项目对应的源码及表结构,开箱即可使用。

说明:后面redis相关操作的功能都会放在此文件夹中,需要相关功能的,只需要获取最新的资源,替换项目即可

       如果大家对相关文章感兴趣,可以关注微信公众号"程序猿小杨",会持续更新优秀文章!欢迎大家 分享、收藏、点赞、在看,您的支持就是我坚持下去的最大动力!谢谢!

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

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

相关文章

链表之第二回

欢迎来到我的&#xff1a;世界 该文章收入栏目&#xff1a;链表 希望作者的文章对你有所帮助&#xff0c;有不足的地方还请指正&#xff0c;大家一起学习交流 ! 目录 前言第一题&#xff1a;反转一个链表第二题&#xff1a;链表内指定区间反转第三题&#xff1a;判断一个链表…

Qt扫盲-QTableView理论总结

QTableView理论总结 一、概述二、导航三、视觉外观四、坐标系统五、示例代码1. 性别代理2. 学生信息模型3. 对应视图 一、概述 QTableView实现了一个tableview 来显示model 中的元素。这个类用于提供之前由QTable类提供的标准表&#xff0c;但这个是使用Qt的model/view架构提供…

【Rust】Rust学习 第十四章进一步认识 Cargo 和 Crates.io

本章会讨论 Cargo 其他一些更为高级的功能&#xff0c;我们将展示如何&#xff1a; 使用发布配置来自定义构建将库发布到 crates.io使用工作空间来组织更大的项目从 crates.io 安装二进制文件使用自定义的命令来扩展 Cargo Cargo 的功能不止本章所介绍的&#xff0c;关于其全…

python 使用 pdf2image 库将PDF转换为图片

在 Ubuntu 上实现网络穿透&#xff1a;手把手教你搭建FRPS服务器 初环境步骤一&#xff1a;安装pdf2image库步骤二&#xff1a;导入必要的库步骤三&#xff1a;指定PDF文件路径步骤四&#xff1a;将PDF转换为图片步骤五&#xff1a;保存图像为图片文件完整代码运行结果 在数字化…

算法通关村第八关——轻松搞定翻转二叉树

二叉树有很多经典算法题&#xff0c;今天我们就来看一下二叉树里的翻转问题。 力扣226,给了一棵二叉树&#xff0c;要将二叉树整体翻转。 分析&#xff1a;观察图中翻转前后的二叉树&#xff0c;我们不难发现&#xff0c;翻转过程中&#xff0c;只需要把每一个节点的左右子节点…

如何在前端实现WebSocket发送和接收UDP消息(多线程模式)

目录 简介&#xff1a;步骤1&#xff1a;创建WebSocket连接步骤2&#xff1a;创建Web Workers步骤3&#xff1a;发送和接收UDP消息&#xff08;多线程模式&#xff09;结束语&#xff1a; 简介&#xff1a; 本文将继续介绍如何在前端应用中利用WebSocket技术发送和接收UDP消息…

jQuery使用(超详细)

一、jQuery介绍 1.JQuery简介 jQuery 是一个高效、精简并且功能丰富的 JavaScript 工具库。它提供的 API 易于使用且兼容众多浏览器&#xff0c;这让诸如 HTML 文档遍历和操作、事件处理、动画和 Ajax 操作更加简单。目前超过90%的网站都使用了jQuery库&#xff0c;jQuery的宗…

为什么贴片电阻的阻值不规律?为了在某精度下做到阻值的全覆盖(对,但不全对),E系列电阻的算法(E12系列值不对的猜想)

1、先放上E系列的电阻表格 E12精度10%&#xff0c;E24精度5%&#xff0c;E96精度1%&#xff1b; 2、以精度作为条件的演算 通常我们选择电阻&#xff0c;要确定电阻的精度&#xff0c;如果以精度作为条件。 以10%精度来说&#xff1a;&#xff08;数值少&#xff0c;好算&am…

大专非科班转码成功自白

大专非科班转码成功自白 文章目录 大专非科班转码成功自白初步学习进阶学习提供阶段面试阶段总结 2023年是博主从业18年以来找工作最难的一年。但程序员这个行业还是被很多毕业生青睐。就业相对比较好&#xff0c;收入相对比较高&#xff0c;虽然面临996&#xff0c;依然给很多…

网络安全--linux下Nginx安装以及docker验证标签漏洞

目录 一、Nginx安装 二、docker验证标签漏洞 一、Nginx安装 1.首先创建Nginx的目录并进入&#xff1a; mkdir /soft && mkdir /soft/nginx/cd /soft/nginx/ 2.下载Nginx的安装包&#xff0c;可以通过FTP工具上传离线环境包&#xff0c;也可通过wget命令在线获取安装包…

从零实战SLAM-第九课(后端优化)

在七月算法报的班&#xff0c;老师讲的蛮好。好记性不如烂笔头&#xff0c;关键内容还是记录一下吧&#xff0c;课程入口&#xff0c;感兴趣的同学可以学习一下。 --------------------------------------------------------------------------------------------------------…

uniapp的UI框架组件库——uView

在写uniapp项目时候&#xff0c;官方所推荐的样式库并不能满足日常的需求&#xff0c;也不可能自己去写相应的样式&#xff0c;费时又费力&#xff0c;所以我们一般会去使用第三方的组件库UI&#xff0c;就像vue里我们所熟悉的elementUI组件库一样的道理&#xff0c;在uniapp中…