使用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
? ?/*** 分類研報購買次數*/public static final String REPORT_CATEGORY_BUY_COUNT = "report_report_category_buy_count:";(2)CacheService.java
? ?@Autowiredprivate RedisTemplate<String, Object> template; ?/*** 增加研報分類閱讀次數(查看文章詳情接口時調用)** @param categoryId*/public void incrReportCategoryReadCount(Long categoryId) {template.opsForZSet().incrementScore(CacheConstant.REPORT_CATEGORY_READ_COUNT, categoryId, 1);} ?/*** 獲取研報分類閱讀排行榜*/public Set<Object> getReportCategoryReadCountRank() {if (template.hasKey(CacheConstant.REPORT_CATEGORY_READ_COUNT)) {//0,-1的參數代表查詢該key下的所有valuereturn template.opsForZSet().reverseRange(CacheConstant.REPORT_CATEGORY_READ_COUNT, 0, -1);} else {return new HashSet<>();}} ? ?/*** 獲取研報分類閱讀排行榜具體分類次數*/public Double getReportCategoryBuyCount(Object o) {return template.opsForZSet().score(CacheConstant.REPORT_CATEGORY_BUY_COUNT, o);}-
這里我們將分類在數據庫中的主鍵id存進去,以便按順序查出來之后去數據庫中查詢對應的分類名。
-
score值就是該文章的閱讀次數,可以直接調用接口獲取
4.Rank.java
? ?public static class Rank implements Serializable {private Long id;private String name;private Integer times;}5.StatisticService.java
? ?@Autowiredprivate CacheService cacheService; ?public StatisticsPlatformResponse platform() { ? ? ? ?//查詢一級分類下的研報閱讀排行List<Rank> readRank = new ArrayList<>();//一次性查詢出所有一級分類,然后和分類排行榜的對應id去匹配List<ReportCategory> oneCategoryList = reportCategoryService.findAllOneCategory(); ?Set<Object> readCountRank = cacheService.getReportCategoryReadCountRank();if (readCountRank != null) {for (Object o : readCountRank) {Rank singReadRank = getRank(oneCategoryList, (Number) o);singReadRank.setTimes(cacheService.getReportCategoryReadCount(o).intValue());readRank.add(singReadRank);}}return readRank;} ?private Rank getRank(List<ReportCategory> oneCategoryList, Number o) {Rank rank = new Rank();rank.setId(o.longValue());rank.setName(getCategoryName(o.longValue(), oneCategoryList));return rank;}/*** 獲取分類名** @param categoryId* @param list* @return*/private String getCategoryName(Long categoryId, List<ReportCategory> list) {for (ReportCategory category : list) {if (category.getId().equals(categoryId)) {return category.getName();}}return null;}?
總結
以上是生活随笔為你收集整理的使用redis的zset实现排行榜的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java内存溢出的定位和分析
- 下一篇: Tomcat调优