Redis 好友关注-朋友圈

该博客详细介绍了如何利用Redis的Set类型实现关注和取关功能,以及检查是否已关注某用户。同时,通过交集操作找出共同关注的好友,并在用户发布内容时,使用Redis的ZSet进行消息推送,确保实时性。此外,还展示了如何按时间戳获取个人收件箱中的朋友圈信息,避免查询重复数据。
摘要由CSDN通过智能技术生成

使用Redis 中的set类型实现关注功能呢

关注取关

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    private static final String FOLLOW_KEY_PREFIX = "follow:user:";

    /**
     * 关注和取关
     *
     * @param followUserId 关注和取关的userId
     * @param isFollow     关注 ,取关 true是关注,false是取关
     * @param userId       自己的userId
     */
    public void follow(Long followUserId, Boolean isFollow, Long userId) {
        String key = FOLLOW_KEY_PREFIX + userId;
        if (isFollow) {
            stringRedisTemplate.opsForSet().add(key, followUserId.toString());
        } else {
            stringRedisTemplate.opsForSet().remove(key, followUserId.toString());
        }
    }

是否关注

    /**
     * 是否已经关注
     *
     * @param followUserId 关注和取关的userId
     * @param userId       自己的userId
     * @return true已关注,false未关注
     */
    public boolean isFollow(Long followUserId, Long userId) {
        String key = FOLLOW_KEY_PREFIX + userId;
        Boolean member = stringRedisTemplate.opsForSet().isMember(key, followUserId);
        return BooleanUtil.isTrue(member);
    }

共同关注的好友

    /**
     * 获取共同关注的好友
     * @param friendId 好友的id
     * @param userId 我的Id
     * @return 所有的共同好友
     */
    public Set<User> commonFollow(Long friendId, Long userId) {
        String myKey = FOLLOW_KEY_PREFIX + userId;
        String friendKey = FOLLOW_KEY_PREFIX + friendId;
        Set<String> intersect = stringRedisTemplate.opsForSet().intersect(myKey, friendKey);
        if (CollectionUtil.isEmpty(intersect)){
            return null;
        }
        List<Long> ids = intersect.stream().map(Long::valueOf).collect(Collectors.toList());
        //模拟数据库根绝userId 集合查询User对象
        Set<User> userSet = new HashSet<>();
        return userSet;
    }

关注推送

当被关注的人发朋友圈时,推送给关注的人内容

 

 

 

 

 

  方便起见使用推模式

@Component
public class BlogService {

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    /**
     * 保存自己发送的朋友圈, 推送到粉丝的收件箱中
     *
     * @param blog
     */
    public void saveBlog(Blog blog) {
        //1.模拟保存数据库
        //saveBolg(blog);
        //2.保存完了将id发送给粉丝
        //从数据库查询关系表中followId为 userId的所有userId
        //select * from follow where follow_id = ?
        List<Long> users = new ArrayList<>();
        for (Long userId : users) {
            String key = "feed:" + userId;
            stringRedisTemplate.opsForZSet().add(key, blog.getId().toString(), System.currentTimeMillis());
        }
    }

    /**
     * 查看自己收件箱的朋友圈信息,不是一次全部查出来,根绝传入的参数,获取时间戳小于max,跳过offset个后的3条数据
     * 这样查询的目的,如果按照角标查询,如果在查询的过程中,又有新的数据插入,则角标变化,导致查询到重复数据,则使用以下方式
     * 当第一次查询时max = System.currentTimeMillis(), offset =0的三条记录
     * 当第二次时,max = 第一次返回的maxTime, offset 为第一次返回的os记录.
     * 这样就可以避免查询到重复的数据
     * 在查询过程中,如果想获取最新的第一条数据,则,max = System.currentTimeMillis(), offset =0 就可以查询到最新的朋友圈
     * @param max 查询时间戳小于max的记录
     * @param offset 在时间戳小于max后跳过几条记录
     * @param userId 查询谁的收件箱
     * @return ScrollResult
     *          data为朋友圈详情
     *          maxTime 查询时间戳的最大值限制
     *          offset 跳过的个数
     */
    public ScrollResult getFriendsBlog(Long max, Integer offset, Long userId) {
        //查询收件箱
        String key = "feed:" + userId;
        Set<ZSetOperations.TypedTuple<String>> typedTuples =
                stringRedisTemplate.opsForZSet().reverseRangeByScoreWithScores(key, 0, max, offset, 3);
        if (CollectionUtil.isEmpty(typedTuples)) {
            return null;
        }
        //解析数据: blogId , minTime(时间戳), offset--跟最小值相同的个数
        List<Long> ids = new ArrayList<>(typedTuples.size());
        long minTime = 0;
        int os = 1;
        for (ZSetOperations.TypedTuple<String> tuple : typedTuples) {
            //获取id
            ids.add(Long.valueOf(tuple.getValue()));
            //获取分数(时间戳)
            long time = tuple.getScore().longValue();
            if (minTime == time) {
                os++;
            } else {
                minTime = time;
                os = 1;
            }
        }
        //存在一个问题,ids的顺序虽然符合需求的,但是数据库查询时in(...)时,就会乱,则
        //sql 改为: select * from Blog  where id (5,1) order by FIELD(id , 5,1)
        List<Blog> list = new ArrayList<>();
        ScrollResult scrollResult = new ScrollResult(list, minTime, os);

        return scrollResult;
    }
}

@Data
@AllArgsConstructor
@NoArgsConstructor
class ScrollResult {
    List<?> data;
    long maxTime;
    int offset;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值