美文网首页
redis实现热搜排行榜及历史搜索记录

redis实现热搜排行榜及历史搜索记录

作者: 任未然 | 来源:发表于2021-12-25 11:16 被阅读0次

    一. 前言

    热搜排行榜实现要点: 性能/简单/时效 .
    redis性能高是公认的, redis的数据结构zset有个score,可以实现排序,redis可以给key设定时效
    历史搜索的实现也差不多,可以用redis的数据结构list(列表)实现,每次在头部插入数据,然后控制列表的长度就行

    二. 示例

    2.1 热搜排行榜-工具类

    import org.apache.commons.collections4.CollectionUtils;
    import org.springframework.data.redis.core.StringRedisTemplate;
    import org.springframework.data.redis.core.ZSetOperations;
    
    import java.io.Serializable;
    import java.time.Duration;
    import java.time.LocalDate;
    import java.time.LocalDateTime;
    import java.time.LocalTime;
    import java.util.List;
    import java.util.Set;
    import java.util.stream.Collectors;
    
    /**
     * 排行榜工具
     *
     * @author 任未然
     * @date 2021/12/25
     */
    public class LeaderboardUtil implements Serializable {
    
        /**
         * redis
         */
        private static StringRedisTemplate redisTemplate;
    
        public static StringRedisTemplate getRedisTemplate(){
            if(null == redisTemplate){
                synchronized (LeaderboardUtil.class){
                    redisTemplate = SpringContextUtil.getBean(StringRedisTemplate.class);
                    return redisTemplate;
                }
            }
            return redisTemplate;
        }
    
        /**
         * 排行榜添加或更新数据score
         * 排行版每天凌晨刷新一遍
         * @param key
         * @param member
         */
        public static void leaderboardAdd(String key, String member){
            // 添加或更新数据
            getRedisTemplate().opsForZSet().incrementScore(key, member, 1);
            // 设置有效期
            LocalDateTime localDateTime = LocalDateTime.of(LocalDate.now(), LocalTime.of(23, 59, 59));
            LocalDateTime now = LocalDateTime.now();
            // 时间差
            Duration between = Duration.between(now, localDateTime);
            getRedisTemplate().expire(key,between);
        }
    
        /**
         * 通过索引区间返回有序集合成指定区间内的成员 分数从高到低
         *
         * @param key   键
         * @param size  获取个数
         * @return 成员集合
         */
        public static List<LeaderboardDto> leaderboardGet(String key, int size) {
            List<LeaderboardDto> leaderboardDtos = null;
            try {
                Set<ZSetOperations.TypedTuple<String>> typedTuples = getRedisTemplate().opsForZSet().reverseRangeWithScores(key, 0, -1);
                if(CollectionUtils.isNotEmpty(typedTuples)){
                    leaderboardDtos = typedTuples.stream().limit(size).map(stringTypedTuple -> {
                        return LeaderboardDto.builder()
                                .value(stringTypedTuple.getValue())
                                .score(stringTypedTuple.getScore())
                                .build();
                    }).collect(Collectors.toList());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return leaderboardDtos;
        }
    }
    
    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    class LeaderboardDto implements Serializable {
    
        private static final long serialVersionUID = 1L;
    
        @ApiModelProperty("值")
        private String value;
    
        @ApiModelProperty("分数")
        private Double score;
    }
    

    2.2 历史搜索-工具类

    import org.springframework.data.redis.core.ListOperations;
    import org.springframework.data.redis.core.StringRedisTemplate;
    
    import java.io.Serializable;
    import java.util.List;
    
    /**
     * 历史搜索工具类
     *
     * @author 任未然
     * @date 2021/12/25
     */
    public class HistoricalSearchUtil implements Serializable {
    
        /**
         * 列表最大长度
         */
        public static final int max_size = 10;
    
        /**
         * redis
         */
        private static ListOperations<String,String> redisTemplate;
    
        public static ListOperations<String,String> getRedisTemplate(){
            if(null == redisTemplate){
                synchronized (LeaderboardUtil.class){
                    redisTemplate = SpringContextUtil.getBean(StringRedisTemplate.class).opsForList();
                    return redisTemplate;
                }
            }
            return redisTemplate;
        }
    
        /**
         * 添加记录
         *
         * @param key   键
         * @param value 值
         * @return boolean
         */
        public static void lpush(String key, String value) {
            try {
                ListOperations<String, String> redisTemplate = getRedisTemplate();
                redisTemplate.leftPush(key, value);
                // 截取列表长度
                redisTemplate.trim(key,0,max_size-1);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 获取列表数据
         *
         * @param key   键
         * @return 元素列表
         */
        public static List<String> lrange(String key) {
            try {
                ListOperations<String, String> redisTemplate = getRedisTemplate();
                return redisTemplate.range(key, 0, -1);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:redis实现热搜排行榜及历史搜索记录

          本文链接:https://www.haomeiwen.com/subject/mtddqrtx.html