專欄集錦,大佬們可以收藏以備不時之需
Spring Cloud實戰(zhàn)專欄:https://blog.csdn.net/superdangbo/category_9270827.html
Python 實戰(zhàn)專欄:https://blog.csdn.net/superdangbo/category_9271194.html
Logback 詳解專欄:https://blog.csdn.net/superdangbo/category_9271502.html
tensorflow專欄:https://blog.csdn.net/superdangbo/category_8691332.html
Redis專欄:https://blog.csdn.net/superdangbo/category_9950790.html
Spring Cloud實戰(zhàn):
Spring Cloud 實戰(zhàn) | 解密Feign底層原理,包含實戰(zhàn)源碼
Spring Cloud 實戰(zhàn) | 解密負載均衡Ribbon底層原理,包含實戰(zhàn)源碼
1024程序員節(jié)特輯文章:
1024程序員狂歡節(jié)特輯 | ELK+ 協(xié)同過濾算法構(gòu)建個性化推薦引擎,智能實現(xiàn)“千人千面”
1024程序員節(jié)特輯 | 解密Spring Cloud Hystrix熔斷提高系統(tǒng)的可用性和容錯能力
1024程序員節(jié)特輯 | ELK+ 用戶畫像構(gòu)建個性化推薦引擎,智能實現(xiàn)“千人千面”
1024程序員節(jié)特輯 | OKR VS KPI誰更合適?
1024程序員節(jié)特輯 | Spring Boot實戰(zhàn) 之 MongoDB分片或復(fù)制集操作
Spring實戰(zhàn)系列文章:
Spring實戰(zhàn) | Spring AOP核心秘笈之葵花寶典
Spring實戰(zhàn) | Spring IOC不能說的秘密?
國慶中秋特輯系列文章:
國慶中秋特輯(八)Spring Boot項目如何使用JPA
國慶中秋特輯(七)Java軟件工程師常見20道編程面試題
國慶中秋特輯(六)大學(xué)生常見30道寶藏編程面試題
國慶中秋特輯(五)MySQL如何性能調(diào)優(yōu)?下篇
國慶中秋特輯(四)MySQL如何性能調(diào)優(yōu)?上篇
國慶中秋特輯(三)使用生成對抗網(wǎng)絡(luò)(GAN)生成具有節(jié)日氛圍的畫作,深度學(xué)習(xí)框架 TensorFlow 和 Keras 來實現(xiàn)
國慶中秋特輯(二)浪漫祝福方式 使用生成對抗網(wǎng)絡(luò)(GAN)生成具有節(jié)日氛圍的畫作
國慶中秋特輯(一)浪漫祝福方式 用循環(huán)神經(jīng)網(wǎng)絡(luò)(RNN)或長短時記憶網(wǎng)絡(luò)(LSTM)生成祝福詩詞
Redis 的有序集合(Sorted Set)是一個基于分數(shù)(score)排序的數(shù)據(jù)結(jié)構(gòu),它在 Redis 中非常重要,常用于實現(xiàn)排行榜、近似計數(shù)器等功能。
Redis 的有序集合(Sorted Set)是基于跳躍表(Skip List)實現(xiàn)的。跳躍表是一種高效的數(shù)據(jù)結(jié)構(gòu),其插入、刪除和查找操作的平均時間復(fù)雜度都是 O(log n),相對于平衡樹(如紅黑樹)的實現(xiàn)要簡單很多。跳躍表的結(jié)構(gòu)類似于鏈表,每個節(jié)點除了保存元素值外,還包含一個指針數(shù)組,分別指向?qū)?yīng)層次的下一個節(jié)點。這種多級指針的設(shè)計,使得跳表可以跨越多個節(jié)點進行快速搜索,同時保證跳表結(jié)構(gòu)的高效性和簡潔性。
有序集合的底層數(shù)據(jù)結(jié)構(gòu)由哈希(Hash)和跳躍表組成。在哈希中,存儲了元素及其關(guān)聯(lián)的評分(分數(shù))。每個元素都有一個唯一的評分,用于確定其在跳躍表中的位置。當(dāng)需要對有序集合進行操作時,Redis 首先通過哈希表找到元素及其評分,然后通過跳躍表進行相應(yīng)的操作。
以下是 Redis 有序集合(Sorted Set)的一些核心操作及其對應(yīng)的核心代碼分析:文章來源:http://www.zghlxwxcb.cn/news/detail-755002.html
- 添加元素(ZADD):
有序集合中的元素添加操作是通過哈希表和跳躍表協(xié)同完成的。首先,Redis 將元素值和評分存儲在哈希表中。然后,根據(jù)評分在跳躍表中找到對應(yīng)的位置,并將新元素插入到該位置。 - 獲取元素(ZRANGE、ZREVRANGE):
有序集合中的獲取元素操作主要依賴于跳躍表。ZRANGE 操作從跳躍表的頭部開始,按照給定的評分范圍返回符合條件的元素。ZREVRANGE 操作則從跳躍表的尾部開始,按照給定的評分范圍返回符合條件的元素。 - 刪除元素(ZREM):
刪除元素操作首先通過哈希表找到對應(yīng)元素,然后在跳躍表中刪除該元素。Redis 只需要刪除哈希表中的指向該元素的指針,跳躍表中的元素會自動上移。 - 更新元素評分(ZINCRBY):
更新元素評分操作僅需修改哈希表中對應(yīng)元素的評分,然后重新計算跳躍表中元素的位置。 - 獲取有序集合長度(ZCARD):
有序集合長度的操作直接查詢哈希表中的鍵值對數(shù)量。 - 隨機獲取元素(ZRANDMEMBER):
隨機獲取元素操作首先從哈希表中隨機選擇一個元素,然后在該元素所在的跳躍表區(qū)間內(nèi)隨機選擇一個元素。
通過以上操作,Redis 實現(xiàn)了高效有序集合(Sorted Set)的數(shù)據(jù)結(jié)構(gòu),提供了高性能的排序和范圍查找功能。
2、實戰(zhàn)
要使用 Spring Boot 和 Redis 實現(xiàn)排行榜功能,你可以遵循以下步驟:文章來源地址http://www.zghlxwxcb.cn/news/detail-755002.html
- 引入依賴
在你的 Spring Boot 項目的 pom.xml 文件中,添加以下依賴:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
</dependencies>
- 配置 Redis
在 application.properties 或 application.yml 文件中配置 Redis 連接信息:
# application.properties
spring.redis.host=localhost
spring.redis.port=6379
# application.yml
spring:
redis:
host: localhost
port: 6379
- 創(chuàng)建 Redis 模板
創(chuàng)建一個 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<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
return redisTemplate;
}
}
- 創(chuàng)建排行榜實體類
創(chuàng)建一個排行榜實體類,包含用戶 ID、分數(shù)等信息:
import java.io.Serializable;
public class RankingEntity implements Serializable {
private String userId;
private double score;
// 構(gòu)造方法、getter 和 setter
}
- 實現(xiàn) Redis 排行榜操作
創(chuàng)建一個服務(wù)類,實現(xiàn)排行榜的相關(guān)操作,如添加分數(shù)、查詢排名等:
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<String, Object> redisTemplate;
private static final String RANKING_KEY = "ranking_list";
/**
* 添加分數(shù)
* @param userId 用戶 ID
* @param score 分數(shù)
*/
public void addScore(String userId, double score) {
ValueOperations<String, RankingEntity> valueOperations = redisTemplate.opsForValue();
valueOperations.set(RANKING_KEY + ":" + userId, score, 60, TimeUnit.SECONDS);
}
/**
* 查詢排名
* @return 排名列表
*/
public List<Object> getRankingList() {
List<Object> 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<String, RankingEntity> valueOperations = redisTemplate.opsForValue();
valueOperations.delete(RANKING_KEY + ":" + userId);
}
/**
* 更新用戶分數(shù)
* @param userId 用戶 ID
* @param score 新的分數(shù)
*/
public void updateUserScore(String userId, double score) {
ValueOperations<String, RankingEntity> valueOperations = redisTemplate.opsForValue();
valueOperations.set(RANKING_KEY + ":" + userId, score, 60, TimeUnit.SECONDS);
}
/**
* 獲取用戶排名列表的長度
* @return 用戶排名列表的長度
*/
public long getUserRankingListSize() {
return redisTemplate.opsForList().size(RANKING_KEY);
}
/**
* 在用戶排名列表中插入用戶分數(shù)
* @param userId 用戶 ID
* @param score 分數(shù)
* @param index 插入位置,0 表示插入到列表頭部,負數(shù)表示插入到列表尾部
*/
public void insertUserScore(String userId, double score, long index) {
List<Object> rankingList = redisTemplate.opsForList().range(RANKING_KEY, 0, -1);
redisTemplate.opsForList().leftPush(RANKING_KEY, score, index);
}
/**
* 在用戶排名列表中刪除用戶分數(shù)
* @param userId 用戶 ID
* @param index 刪除位置,0 表示刪除第一個元素,1 表示刪除第二個元素,依此類推
*/
public void deleteUserScore(String userId, long index) {
List<Object> 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 添加的分數(shù)
*/
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<Object> getUserRankingList() {
return redisTemplate.opsForList().range(RANKING_KEY, 0, -1);
}
/**
* 設(shè)置用戶排名列表的長度
* @param length 用戶排名列表的新長度
*/
public void setUserRankingListLength(long length) {
redisTemplate.opsForList().setSize(RANKING_KEY, length);
}
/**
* 獲取用戶排名
*
* @param userId 用戶 ID
* @return 用戶排名,如果用戶不存在,返回 -1
*/
public int getUserRanking(String userId) {
List<Object> 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);
}
/**
* 獲取用戶排名列表中的用戶分數(shù)
*
* @param userId 用戶 ID
* @return 用戶排名列表中的用戶分數(shù),如果用戶不存在,返回 null
*/
public Object getUserRanking(String userId) {
ValueOperations<String, RankingEntity> valueOperations = redisTemplate.opsForValue();
return valueOperations.get(RANKING_KEY + ":" + userId);
}
/**
* 是否存在用戶
*
* @param userId 用戶 ID
* @return 是否存在用戶
*/
public boolean existsUser(String userId) {
ValueOperations<String, RankingEntity> valueOperations = redisTemplate.opsForValue();
return valueOperations.hasKey(RANKING_KEY + ":" + userId);
}
/**
* 清除所有用戶排名數(shù)據(jù)
*/
public void clearAllUserRankingData() {
redisTemplate.delete(RANKING_KEY);
}
}
到了這里,關(guān)于Redis實戰(zhàn) | 使用Redis 的有序集合(Sorted Set)實現(xiàn)排行榜功能,和Spring Boot集成的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!