首页 > 数据库 >基于Redis实现关注、取关、共同关注及消息推送(含源码)

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

时间:2023-08-18 18:35:45浏览次数:44  
标签:分数 Redis userId Long id 取关 key follow 源码

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

一、简介

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

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

二、实现关注和取关

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

2.1、关注和取消关注功能

业务流程图:

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

核心代码实现:

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);  //当前登录人员ID
            follow.setFollowUserId(followUserId);  //关注用户的id
            boolean isSuccess = save(follow);
            if (isSuccess) {
                // 把关注用户的id,放入redis的set集合 sadd userId followerUserId
                stringRedisTemplate.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();
    }

结果展示:

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

2.2、共同关注功能

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

2.3、使用的redis命令如下:

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

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

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、结果展示

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

三、关注推送

3.1、Feed流模式

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

3.2、常见模式

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

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

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

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

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

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

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

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

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

3.3、三种实现方案

3.3.1、拉模式

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

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

3.3.2、推模式

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

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

3.3.3、推拉结合模式

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

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

3.3.4、总结

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

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

四、案例

4.1、需求分析

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

滚动分页:

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

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 0
ZREVRANGEBYSCORE myset (100 0 WITHSCORES
ZREVRANGEBYSCORE 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中实现滚动分页功能:

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

4.3、业务流程图

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

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.获取粉丝id
            Long uId = follow.getUserId();
            // 4.2.feed推送消息
            String key = FEED_KEY + uId;
            stringRedisTemplate.opsForZSet().add(key, blog.getId().toString(), System.currentTimeMillis());
        }
        // 5.返回id
        return 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 count
        String 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(时间戳)、offset
        List<Long> ids = new ArrayList<>(typedTuples.size());
        long minTime = 0; // 2
        int os = 1; // 2
        for (ZSetOperations.TypedTuple<String> tuple : typedTuples) { // 5 4 4 2 2
            // 4.1.获取id
            ids.add(Long.valueOf(tuple.getValue()));
            // 4.2.获取分数(时间戳)
            long time = tuple.getScore().longValue();
            if(time == minTime){
                os++;
            }else{
                minTime = time;
                os = 1;
            }
        }
        // 5.根据id查询blog
        String 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);
    }

备注:

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

4.4.3、请求参数

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

参考案例:

{
  "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实现关注、取关、共同关注及消息推送(含源码)_关注_19

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

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

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

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

标签:分数,Redis,userId,Long,id,取关,key,follow,源码
From: https://blog.51cto.com/u_11866810/7140070

相关文章

  • 金融行业招聘数据分析系统的设计与实现-计算机毕业设计源码+LW文档
    摘要随着社会经济的快速发展,人们的生活水平得到了显著提高,但随之而来的社会问题也越来越多。其中最为显著的就是就业问题。为此,招聘信息的展示也变得越来越为重要。但是在大量的招聘信息中,人们在提取自己最想要的信息时变得不那么容易,对于应聘者也是如此。本系统通过对网络爬虫的......
  • AOP源码解析:AspectJExpressionPointcutAdvisor类
    先看看AspectJExpressionPointcutAdvisor的类图再了解一下切点(Pointcut)表达式,它指定触发advice的方法,可以精确到返回参数,参数类型,方法名1packageconcert;23publicinterfacePerformance{4voidperform();5}AspectJExpressionPointcutAdvisor源码,官......
  • Redis安装配置使用笔记
    Redis是一个基于内存的key-value结构数据库基于内存存储,读写性能高适用于存储热点数据(热点商品,资讯,新闻,秒杀系统) 1.使用Redis1.在Linux上安装Redis 2.在win系统安装直接解压即可  3.启动RedisLinux中在Redis目录下的src目录下直接运行 ./redis-server 4.连接Redis服务Linu......
  • 配置Redis哨兵集群所遇到的问题
    配置Redis哨兵集群时日志显示+sdownslave的问题一、配置及其环境描述(问题产生的原因是因为Redis复制中主节点对从节点的ip配置错误,从而导致哨兵无法识别从节点,进而无法进行故障转移)1.操作系统:Linux 虚拟机:VMwareWorkstation16Pro、WSLRedis主从复制配置为在VM虚拟机上......
  • 分布式存储系统举例剖析(elasticsearch,kafka,redis-cluster)
    1.概述对于分布式系统,人们首先对现实中的分布式系统进行高层抽象,然后做出各种假设,发展了诸如CAP,FLP等理论,提出了很多一致性模型,Paxos是其中最璀璨的明珠。我们对分布式系统的时序,复制模式,一致性等基础理论特别关注。在共识算法的基础上衍生了选举算法,并且为分布式事务提供......
  • 直播平台源码之实现网络请求的方法
    直播平台源码开发中如果你不会网络请求,那么你开发的应用软件就是一具没有灵魂的枯骨。当你下载完软件后会要求你给与权限,否则就没办法使用,网络请求也需要对应的权限,否则就没法进行联网操作。在直播平台源码开发中首先在AndroidManifest.xml文件中添加网络请求权限要在manifest......
  • 如何在视频直播app源码开发中实现开屏广告功能
    APP开屏广告就目前来说是一个很常见的广告形式,我们现在打开各个APP几乎都会有开屏广告的身影,开屏广告也成了吸引用户注意力和实现盈利的主要方式,所以在视频直播app源码开发,开屏广告功能就显得尤为重要。一、视频直播app源码之开屏广告作用:广告、营销推广界面组成:广告、跳过(倒计......
  • python监控redis demo
    下载aioredis为了提升性能我们使用一部redispipinstallaioredisdemo:importasyncioimportaioredis#每隔10s获取redis信息asyncdefmonitor_redis(host,port,interval):#建立异步Redis连接redis_uri=f"redis://{host}:{port}"redis=awaitai......
  • 悬赏平台APP系统源码
      悬赏平台APP软件是一款在线上做任务,拉新,充场的软件,任何一个用户在平台上注册账号,发布任务,领取任务并获得佣金。本文就一悬赏任务APP软件对功能上的事项进行分析,看看都有哪些功能。  1.任务源  悬赏平台APP展示者所有的任务平台类型,任务做法流程,任务要求,有充场,拉新,......
  • CentOS7源码安装JDK8☘️
    1.下载jdk  Java版本支持路线图 Java9、Java10、Java12、Java13、Java14、Java15和Java16均为短期版本,建议不要使用以上版本。官网下载如有旧版本请先卸载openjdk:[root@localhost~]#yumerase`rpm-qa|grepopenjdk`-y2.解压安装:[root@localhost~]#tarxvz......