使用redis的zset实现排行榜

1.使用场景

现在公司有个项目,类似于今日头条,需要实现对应分类阅读排行榜的功能。

每一篇文章所属于一个分类,当用户阅读该文章时,阅读次数+1,排行榜实时变化。

2.redis的ZSet数据结构

zset为有序集合。就是在set的基础上,添加了一个score值。zset的每一个成员都有一个分数与之对应,并且分数可以重复。score就相当于权重,可以根据score值进行排序展示。

项目中使用了SpringBoot整合的redisTemplate

常用方法如下:

  • Boolean add(K key, V value, double score):新增一个有序集合,存在的话为false,不存在的话为true

  • Long add(K key, Set<TypedTuple<V>> tuples):新增一个有序集合

  • Long remove(K key, Object... values):从有序集合中移除一个或者多个元素

  • Double incrementScore(K key, V value, double delta):增加元素的score值,并返回增加后的值

  • Set<V> range(K key, long start, long end):通过索引区间返回有序集合成指定区间内的成员,其中有序集成员按分数值递增(从小到大)顺序排列

  • Set<TypedTuple<V>> rangeWithScores(K key, long start, long end):通过索引区间返回有序集合成指定区间内的成员对象,其中有序集成员按分数值递增(从小到大)顺序排列

  • Set<V> rangeByScore(K key, double min, double max):通过分数返回有序集合指定区间内的成员,其中有序集成员按分数值递增(从小到大)顺序排列

  • Set<V> reverseRange(K key, long start, long end):通过索引区间返回有序集合成指定区间内的成员,其中有序集成员按分数值递减(从大到小)顺序排列

  • Double score(K key, Object o):获取指定成员的score值

3.代码实例

(1)项目中的缓存常量类

CacheConstant.java


 
 
  1.     /**
  2.     * 分类研报购买次数
  3.     */
  4.     public static final String REPORT_CATEGORY_BUY_COUNT = "report_report_category_buy_count:";

(2)CacheService.java


 
 
  1.     @Autowired
  2.     private RedisTemplate<String, Object> template;
  3.     /**
  4.     * 增加研报分类阅读次数(查看文章详情接口时调用)
  5.     *
  6.     * @param categoryId
  7.     */
  8.     public void incrReportCategoryReadCount(Long categoryId) {
  9.        template.opsForZSet().incrementScore(CacheConstant.REPORT_CATEGORY_READ_COUNT, categoryId, 1);
  10.   }
  11.     /**
  12.     * 获取研报分类阅读排行榜
  13.     */
  14.     public Set<Object> getReportCategoryReadCountRank() {
  15.         if (template.hasKey(CacheConstant.REPORT_CATEGORY_READ_COUNT)) {
  16.             //0,-1的参数代表查询该key下的所有value
  17.             return template.opsForZSet().reverseRange(CacheConstant.REPORT_CATEGORY_READ_COUNT, 0, - 1);
  18.       } else {
  19.             return new HashSet<>();
  20.       }
  21.   }
  22.     /**
  23.     * 获取研报分类阅读排行榜具体分类次数
  24.     */
  25.     public Double getReportCategoryBuyCount(Object o) {
  26.         return template.opsForZSet().score(CacheConstant.REPORT_CATEGORY_BUY_COUNT, o);
  27.   }
  • 这里我们将分类在数据库中的主键id存进去,以便按顺序查出来之后去数据库中查询对应的分类名。

  • score值就是该文章的阅读次数,可以直接调用接口获取

4.Rank.java


 
 
  1.     public static class Rank implements Serializable {
  2.         private Long id;
  3.         private String name;
  4.         private Integer times;
  5.   }

5.StatisticService.java


 
 
  1.     @Autowired
  2.     private CacheService cacheService;
  3. public StatisticsPlatformResponse platform() {        
  4. //查询一级分类下的研报阅读排行
  5.        List<Rank> readRank = new ArrayList<>();
  6.         //一次性查询出所有一级分类,然后和分类排行榜的对应id去匹配
  7.        List<ReportCategory> oneCategoryList = reportCategoryService.findAllOneCategory();
  8.        Set<Object> readCountRank = cacheService.getReportCategoryReadCountRank();
  9.         if (readCountRank != null) {
  10.             for (Object o : readCountRank) {
  11.                Rank singReadRank = getRank(oneCategoryList, (Number) o);
  12.                singReadRank.setTimes(cacheService.getReportCategoryReadCount(o).intValue());
  13.                readRank.add(singReadRank);
  14.           }
  15.       }
  16.       return readRank;
  17.   }
  18.     private Rank getRank(List<ReportCategory> oneCategoryList, Number o) {
  19.        Rank rank = new Rank();
  20.        rank.setId(o.longValue());
  21.        rank.setName(getCategoryName(o.longValue(), oneCategoryList));
  22.         return rank;
  23.   }
  24. /**
  25. * 获取分类名
  26. *
  27. * @param categoryId
  28. * @param list
  29. * @return
  30. */
  31. private String getCategoryName(Long categoryId, List<ReportCategory> list) {
  32. for (ReportCategory category : list) {
  33. if (category.getId().equals(categoryId)) {
  34. return category.getName();
  35. }
  36. }
  37. return null;
  38. }

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值