精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

使用Redis的有序集合實現排行榜功能和Spring Boot集成

馬哥Linux運維 ? 來源:csdn ? 2023-11-20 10:15 ? 次閱讀

Redis 的有序集合(Sorted Set)是一個基于分數(score)排序的數據結構,它在 Redis 中非常重要,常用于實現排行榜、近似計數器等功能。

Redis 的有序集合(Sorted Set)是基于跳躍表(Skip List)實現的。跳躍表是一種高效的數據結構,其插入、刪除和查找操作的平均時間復雜度都是 O(log n),相對于平衡樹(如紅黑樹)的實現要簡單很多。跳躍表的結構類似于鏈表,每個節點除了保存元素值外,還包含一個指針數組,分別指向對應層次的下一個節點。這種多級指針的設計,使得跳表可以跨越多個節點進行快速搜索,同時保證跳表結構的高效性和簡潔性。

有序集合的底層數據結構由哈希(Hash)和跳躍表組成。在哈希中,存儲了元素及其關聯的評分(分數)。每個元素都有一個唯一的評分,用于確定其在跳躍表中的位置。當需要對有序集合進行操作時,Redis 首先通過哈希表找到元素及其評分,然后通過跳躍表進行相應的操作。

以下是 Redis 有序集合(Sorted Set)的一些核心操作及其對應的核心代碼分析:

添加元素(ZADD):

有序集合中的元素添加操作是通過哈希表和跳躍表協同完成的。首先,Redis 將元素值和評分存儲在哈希表中。然后,根據評分在跳躍表中找到對應的位置,并將新元素插入到該位置。

獲取元素(ZRANGE、ZREVRANGE):

有序集合中的獲取元素操作主要依賴于跳躍表。ZRANGE 操作從跳躍表的頭部開始,按照給定的評分范圍返回符合條件的元素。ZREVRANGE 操作則從跳躍表的尾部開始,按照給定的評分范圍返回符合條件的元素。

刪除元素(ZREM):

刪除元素操作首先通過哈希表找到對應元素,然后在跳躍表中刪除該元素。Redis 只需要刪除哈希表中的指向該元素的指針,跳躍表中的元素會自動上移。

更新元素評分(ZINCRBY):

更新元素評分操作僅需修改哈希表中對應元素的評分,然后重新計算跳躍表中元素的位置。

獲取有序集合長度(ZCARD):

有序集合長度的操作直接查詢哈希表中的鍵值對數量。

隨機獲取元素(ZRANDMEMBER):

隨機獲取元素操作首先從哈希表中隨機選擇一個元素,然后在該元素所在的跳躍表區間內隨機選擇一個元素。

通過以上操作,Redis 實現了高效有序集合(Sorted Set)的數據結構,提供了高性能的排序和范圍查找功能。

2、實戰

要使用 Spring Boot 和 Redis 實現排行榜功能,你可以遵循以下步驟:

引入依賴

在你的 Spring Boot 項目的 pom.xml 文件中,添加以下依賴:

  
      
        org.springframework.boot  
        spring-boot-starter-data-redis  
      
 

配置 Redis

在 application.properties 或 application.yml 文件中配置 Redis 連接信息

# application.properties  
spring.redis.host=localhost  
spring.redis.port=6379  
# application.yml  
spring:  
  redis:  
    host: localhost  
    port: 6379  

創建 Redis 模板

創建一個 RedisTemplate Bean:

import org.springframework.context.annotation.Bean;  
import org.springframework.context.annotation.Configuration;  
import org.springframework.data.redis.connection.RedisConnectionFactory;  
import org.springframework.data.redis.core.RedisTemplate;  
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;  
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration  
public class RedisConfig {
    @Bean  
    public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {  
        RedisTemplate redisTemplate = new RedisTemplate<>();  
        redisTemplate.setConnectionFactory(redisConnectionFactory);  
        redisTemplate.setKeySerializer(new StringRedisSerializer());  
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());  
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());  
        redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());  
        return redisTemplate;  
    }  
}

創建排行榜實體類

創建一個排行榜實體類,包含用戶 ID、分數等信息:

import java.io.Serializable;
public class RankingEntity implements Serializable {
    private String userId;  
    private double score;
    // 構造方法、getter 和 setter 

實現 Redis 排行榜操作

創建一個服務類,實現排行榜的相關操作,如添加分數、查詢排名等:

import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.data.redis.core.RedisTemplate;  
import org.springframework.data.redis.core.ValueOperations;  
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;
@Service  
public class RankingService {
    @Autowired  
    private RedisTemplate redisTemplate;
    private static final String RANKING_KEY = "ranking_list";
    /**  
     * 添加分數  
     * @param userId 用戶 ID  
     * @param score 分數  
     */  
    public void addScore(String userId, double score) {  
        ValueOperations valueOperations = redisTemplate.opsForValue();  
        valueOperations.set(RANKING_KEY + ":" + userId, score, 60, TimeUnit.SECONDS);  
    }
    /**  
     * 查詢排名  
     * @return 排名列表  
     */  
    public List getRankingList() {  
        List rankingList = redisTemplate.opsForList().range(RANKING_KEY, 0, -1);  
        return rankingList;  
    }
    /**  
     * 查詢用戶排名  
     * @param userId 用戶 ID  
     * @return 用戶排名  
     */  
    public Object getUserRanking(String userId) {  
        return redisTemplate.opsForValue().get(RANKING_KEY + ":" + userId);  
    }
     * @param userId 用戶 ID  
     */  
    public void deleteUserScore(String userId) {  
        ValueOperations valueOperations = redisTemplate.opsForValue();  
        valueOperations.delete(RANKING_KEY + ":" + userId);  
    }
    /**  
     * 更新用戶分數  
     * @param userId 用戶 ID  
     * @param score 新的分數  
     */  
    public void updateUserScore(String userId, double score) {  
        ValueOperations valueOperations = redisTemplate.opsForValue();  
        valueOperations.set(RANKING_KEY + ":" + userId, score, 60, TimeUnit.SECONDS);  
    }
    /**  
     * 獲取用戶排名列表的長度  
     * @return 用戶排名列表的長度  
     */  
    public long getUserRankingListSize() {  
        return redisTemplate.opsForList().size(RANKING_KEY);  
    }
    /**  
     * 在用戶排名列表中插入用戶分數  
     * @param userId 用戶 ID  
     * @param score 分數  
     * @param index 插入位置,0 表示插入到列表頭部,負數表示插入到列表尾部  
     */  
    public void insertUserScore(String userId, double score, long index) {  
        List rankingList = redisTemplate.opsForList().range(RANKING_KEY, 0, -1);  
        redisTemplate.opsForList().leftPush(RANKING_KEY, score, index);  
    }
    /**  
     * 在用戶排名列表中刪除用戶分數  
     * @param userId 用戶 ID  
     * @param index 刪除位置,0 表示刪除第一個元素,1 表示刪除第二個元素,依此類推  
     */  
    public void deleteUserScore(String userId, long index) {  
        List rankingList = redisTemplate.opsForList().range(RANKING_KEY, 0, -1);  
        redisTemplate.opsForList().rightPop(RANKING_KEY, index);  
    }
    /**  
     * 獲取用戶排名列表中的最后一個元素  
     * @return 用戶排名列表中的最后一個元素  
     */  
    public Object getLastUserScore() {  
        return redisTemplate.opsForList().rightPop(RANKING_KEY);  
    }
    /**  
     * 獲取用戶排名列表中的第一個元素  
     * @return 用戶排名列表中的第一個元素  
     */  
    public Object getFirstUserScore() {  
        return redisTemplate.opsForList().leftPop(RANKING_KEY);  
    }
    /**  
     * 在用戶排名列表中添加元素  
     * @param score 添加的分數  
     */  
    public void addUserScore(double score) {  
        redisTemplate.opsForList().rightPush(RANKING_KEY, score);  
    }
    /**  
     * 在用戶排名列表中刪除元素  
     * @param index 刪除位置,0 表示刪除第一個元素,1 表示刪除第二個元素,依此類推  
     */  
    public void deleteUserScore(long index) {  
        redisTemplate.opsForList().rightPop(RANKING_KEY, index);  
    }
    /**  
     * 獲取用戶排名列表  
     * @return 用戶排名列表  
     */  
    public List getUserRankingList() {  
        return redisTemplate.opsForList().range(RANKING_KEY, 0, -1);  
    }
    /**  
     * 設置用戶排名列表的長度  
     * @param length 用戶排名列表的新長度  
     */  
    public void setUserRankingListLength(long length) {  
        redisTemplate.opsForList().setSize(RANKING_KEY, length);  
    }
    /**  
     * 獲取用戶排名  
     *  
     * @param userId 用戶 ID  
     * @return 用戶排名,如果用戶不存在,返回 -1  
     */  
    public int getUserRanking(String userId) {  
        List rankingList = getRankingList();  
        Object userScore = getUserRanking(userId);  
        if (userScore == null) {  
            return -1;  
        }
                     int rank = 0;    
        for (Object score : rankingList) {    
            if (score.equals(userScore)) {    
                break;    
            }    
            rank++;    
        }    
        return rank;    
    }
    /**  
     * 獲取用戶排名列表中的指定位置的元素  
     *  
     * @param index 指定位置,從 0 開始  
     * @return 用戶排名列表中的指定位置的元素  
     */  
    public Object getUserRankingListElement(long index) {  
        return redisTemplate.opsForList().range(RANKING_KEY, 0, -1).get(index);  
    }
    /**  
     * 獲取用戶排名列表中的用戶分數  
     *  
     * @param userId 用戶 ID  
     * @return 用戶排名列表中的用戶分數,如果用戶不存在,返回 null  
     */  
    public Object getUserRanking(String userId) {  
        ValueOperations valueOperations = redisTemplate.opsForValue();  
        return valueOperations.get(RANKING_KEY + ":" + userId);  
    }
    /**  
     * 是否存在用戶  
     *  
     * @param userId 用戶 ID  
     * @return 是否存在用戶  
     */  
    public boolean existsUser(String userId) {  
        ValueOperations valueOperations = redisTemplate.opsForValue();  
        return valueOperations.hasKey(RANKING_KEY + ":" + userId);  
    }
    /**  
     * 清除所有用戶排名數據  
     */  
    public void clearAllUserRankingData() {  
        redisTemplate.delete(RANKING_KEY);  
    }  
}







審核編輯:劉清

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 計數器
    +關注

    關注

    32

    文章

    2254

    瀏覽量

    94371
  • Redis
    +關注

    關注

    0

    文章

    371

    瀏覽量

    10848

原文標題:Redis實戰 | 使用Redis 的有序集合(Sorted Set)實現排行榜功能,和Spring Boot集成

文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    HarmonyOS開發案例:【排行榜頁面】

    本課程使用聲明式語法和組件化基礎知識,搭建一個可刷新的排行榜頁面。在排行榜頁面中,使用循環渲染控制語法來實現列表數據渲染,使用@Builder創建排行列表布局內容,使用裝飾器@Stat
    的頭像 發表于 04-30 16:16 ?1906次閱讀
    HarmonyOS開發案例:【<b class='flag-5'>排行榜</b>頁面】

    中國IC設計公司排行榜

    作者:林曉林  中國IC設計公司排行榜:近日,市場調研公司iSuppli出臺了2005年度中國IC設計公司排行榜,與中國半導體協會的排名不同,此次名列榜首的是來自香港的晶門
    發表于 05-26 14:29

    資料下載總排行榜

    資料下載總排行榜,怎么就那幾個啊,怎么下載到人氣高的資料?資料茫茫,我相信大家的眼睛雪亮的。求方法收集些好的資料。。。
    發表于 03-05 16:24

    各種排行榜匯總貼!!!!!

    本帖最后由 dongyumin 于 2013-7-31 11:39 編輯 1.2012網上各地年終獎排行榜,科技、電子企業全面領跑!https://bbs.elecfans.com
    發表于 07-30 11:55

    2014年10月 TIOBE 編程語言排行榜發布

    2014年10月的 TIOBE 編程語言排行榜發布了,該版本最大的兩點是 Google 的 Dart 語言首次進入前 20 名。其競爭者包括 CoffeeScript 目前排名 133,TypeScript 排名 122.想知道完整的排名表格請回復
    發表于 12-08 13:46

    小米放出“手機電量排行榜” 為續航神機Max 2造勢

    小米手機家族的電量排行榜,并向網友征詢:“你覺得小米Max2多大電量夠你用? ”從排行榜來看,現款小米Max以4850mAh的容量排名第一,其次是小米MIX(4400mAh)、紅米4(4100mAh
    發表于 06-03 14:20

    Redis有序集合詳細步驟

    利用Redis Sorted Set實現排行榜功能
    發表于 05-21 14:09

    MapReduce框架音樂排行榜案例

    Hadoop綜合實戰之MapReduce運算優化——音樂排行榜
    發表于 10-16 12:20

    Spring bootRedis的使用

    【本人禿頂程序員】springboot專輯:Spring bootRedis的使用
    發表于 03-27 11:42

    求職必知獨角獸公司排行榜

    世界第 3 的滴滴裁員,求職必知獨角獸公司排行榜
    發表于 06-18 07:30

    2019年2月編程語言排行榜分享

    2019年2月編程語言排行榜
    發表于 07-14 10:28

    2020年最新主板型號排行榜 精選資料推薦

    2020年最新主板型號排行榜2020主板型號天梯圖2020主板選購指南一、Intel、AMD電腦主板的辨別二、主板芯片組級別三、板形四、主板對電腦性能有什么影響在使用電腦的時候,我們有時候會需要更換
    發表于 07-26 06:16

    玩轉Redis-使用有序集合(sorted sets)實現投票游戲

    中所有參與的人的排行榜。* zinterstore 是求兩個集合的交集,通過它,可以獲得同時參加多個候選人投票的名單列表。* zrevrank 方便的查詢某個元素在有序集合中的位置,也
    的頭像 發表于 09-26 12:40 ?2569次閱讀

    基于排行榜功能使用redis中的有序集合實現

    排行榜功能是一個很普遍的需求,對于這類需求如果數據總量過大用mysql實現的話會很浪費性能。
    的頭像 發表于 10-21 09:59 ?987次閱讀

    Redis的常用場景有哪些

    策略,所以,現在Redis用在緩存的場合非常多。 2、排行榜 很多網站都有排行榜應用的,如京東的月度銷量榜單、商品按時間的上新排行榜等。Redis
    的頭像 發表于 10-09 10:44 ?641次閱讀