Redis 好友关注-朋友圈

使用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 commonFollow(Long friendId, Long userId) {
        String myKey = FOLLOW_KEY_PREFIX + userId;
        String friendKey = FOLLOW_KEY_PREFIX + friendId;
        Set intersect = stringRedisTemplate.opsForSet().intersect(myKey, friendKey);
        if (CollectionUtil.isEmpty(intersect)){
            return null;
        }
        List ids = intersect.stream().map(Long::valueOf).collect(Collectors.toList());
        //模拟数据库根绝userId 集合查询User对象
        Set userSet = new HashSet<>();
        return userSet;
    }

关注推送

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

Redis 好友关注-朋友圈_第1张图片

 Redis 好友关注-朋友圈_第2张图片

 Redis 好友关注-朋友圈_第3张图片

 Redis 好友关注-朋友圈_第4张图片

 Redis 好友关注-朋友圈_第5张图片

 Redis 好友关注-朋友圈_第6张图片

  方便起见使用推模式

@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 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> typedTuples =
                stringRedisTemplate.opsForZSet().reverseRangeByScoreWithScores(key, 0, max, offset, 3);
        if (CollectionUtil.isEmpty(typedTuples)) {
            return null;
        }
        //解析数据: blogId , minTime(时间戳), offset--跟最小值相同的个数
        List ids = new ArrayList<>(typedTuples.size());
        long minTime = 0;
        int os = 1;
        for (ZSetOperations.TypedTuple 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 list = new ArrayList<>();
        ScrollResult scrollResult = new ScrollResult(list, minTime, os);

        return scrollResult;
    }
}

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

你可能感兴趣的:(redis,redis,java,数据库)