完成学习redis数据结构

This commit is contained in:
2026-03-07 14:43:43 +08:00
parent b7ad9b57c6
commit 88b40ba4a2
2 changed files with 95 additions and 53 deletions

View File

@@ -19,10 +19,14 @@
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>junit</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>junit</artifactId> <artifactId>spring-boot-starter-web</artifactId>
<version>3.8.1</version> </dependency>
<scope>test</scope> <!-- Spring Boot Redis显式绑定版本 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.4.6</version> <!-- 推荐使用稳定版 -->
</dependency> </dependency>
</dependencies> </dependencies>
</project> </project>

View File

@@ -1,10 +1,15 @@
package cn.mayiming; package cn.mayiming;
import redis.clients.jedis.Jedis;
import java.net.URI; import java.net.URI;
import java.net.http.HttpClient; import java.net.http.HttpClient;
import java.net.http.HttpRequest; import java.net.http.HttpRequest;
import java.net.http.HttpResponse; import java.net.http.HttpResponse;
import java.time.Duration; import java.time.Duration;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@@ -15,64 +20,97 @@ import java.util.concurrent.TimeUnit;
*/ */
public class App public class App
{ {
// 网关地址(请根据你的实际环境修改)
private static final String GATEWAY_URL = "http://localhost:8080/order";
// 请求体JSON数据
private static final String REQUEST_BODY = "{\"username\":\"admin\"}";
// 总请求次数
private static final int TOTAL_REQUESTS = 50;
public static void main(String[] args) { public static void main(String[] args) {
// 1. 创建HttpClient实例设置超时时间10秒 Jedis jedis = null;
HttpClient httpClient = HttpClient.newBuilder() try {
.connectTimeout(Duration.ofSeconds(10)) // 建立 Redis 连接
.executor(Executors.newFixedThreadPool(5)) // 线程池,控制并发数 jedis = new Jedis("localhost", 6379);
.build(); // 可选Redis 密码认证
// jedis.auth("你的Redis密码");
// 2. 循环发送30次请求 // ==================== ZSet 结构核心操作 ====================
for (int i = 1; i <= TOTAL_REQUESTS; i++) { // ZSet 特点有序、元素唯一member 不重复、每个元素关联一个分数score按score排序
int requestNum = i; // 内部类引用需要final所以定义临时变量 // 场景1商品销量排行榜按销量从高到低排序
try { String salesRankKey = "rank:product:sales"; // 商品销量排行榜
// 构建POST请求
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(GATEWAY_URL))
.header("Content-Type", "application/json") // 指定JSON格式
.POST(HttpRequest.BodyPublishers.ofString(REQUEST_BODY))
.timeout(Duration.ofSeconds(10))
.build();
// 发送请求并获取响应 // 方式1添加元素member=商品IDscore=销量重复添加会更新score
HttpResponse<String> response = httpClient.send( jedis.zadd(salesRankKey, 500, "product1001"); // 商品1001销量500
request, jedis.zadd(salesRankKey, 800, "product1002"); // 商品1002销量800
HttpResponse.BodyHandlers.ofString() jedis.zadd(salesRankKey, 1200, "product1003");// 商品1003销量1200
); jedis.zadd(salesRankKey, 800, "product1002");// 重复添加仅更新score这里score不变
System.out.println("商品销量排行榜初始化完成");
// 3. 解析响应结果,判断是否成功 // 方式2按score升序/降序查询(核心!排行榜核心操作)
int statusCode = response.statusCode(); // zrange升序查询0=第1名-1=最后1名WITHSCORES 显示分数
boolean isSuccess = statusCode >= 200 && statusCode < 300; Set<String> ascRank = (Set<String>) jedis.zrange(salesRankKey, 0, -1);
System.out.println("\n销量升序排行榜商品ID:销量):" + ascRank);
// 打印请求结果 // zrevrange降序查询最常用排行榜从高到低
System.out.printf("第 %d 次请求:%s | 状态码:%d | 响应体:%s%n", Set<String> descRank = (Set<String>) jedis.zrevrange(salesRankKey, 0, -1);
requestNum, System.out.println("销量降序排行榜商品ID:销量):" + descRank);
isSuccess ? "成功" : "失败",
statusCode,
response.body().length() > 200 ? response.body().substring(0, 200) + "..." : response.body()
);
// 可选:每次请求后短暂休眠,避免压垮网关(可根据需要调整 // 方式3查询指定元素的分数查看单个商品销量
TimeUnit.MILLISECONDS.sleep(100); Double sales1002 = jedis.zscore(salesRankKey, "product1002");
System.out.println("商品1002的销量" + sales1002);
} catch (Exception e) { // 方式4更新元素分数销量增加比如商品1001新增200单
// 捕获所有异常,标记请求失败 jedis.zincrby(salesRankKey, 200, "product1001"); // score += 200
System.out.printf("第 %d 次请求:失败 | 异常信息:%s%n", System.out.println("商品1001销量+200后" + jedis.zscore(salesRankKey, "product1001"));
requestNum,
e.getMessage() // 方式5查询元素排名降序从0开始计数
); Long rank1003 = jedis.zrevrank(salesRankKey, "product1003");
System.out.println("商品1003的销量排名第1名=0" + (rank1003 + 1) + "");
// 方式6按分数范围查询比如销量≥800的商品
Set<String> highSales = (Set<String>) jedis.zrangeByScore(salesRankKey, 800, Double.MAX_VALUE);
System.out.println("销量≥800的商品" + highSales);
// ==================== 场景2延迟队列按时间戳排序 ====================
String delayQueueKey = "queue:delay:order"; // 订单延迟队列
// 核心逻辑score=执行时间戳比如10秒后执行、30秒后执行
long now = System.currentTimeMillis() / 1000; // 当前时间戳(秒)
jedis.zadd(delayQueueKey, now + 10, "订单100110秒后自动取消"); // 10秒后处理
jedis.zadd(delayQueueKey, now + 30, "订单100230秒后自动确认收货"); // 30秒后处理
System.out.println("\n延迟队列初始化完成当前时间戳" + now);
// 方式7获取需要执行的任务score ≤ 当前时间戳的元素)
Set<String> needExecute = (Set<String>) jedis.zrangeByScore(delayQueueKey, 0, now, 0, 10); // 取前10个待执行任务
System.out.println("当前需要执行的延迟任务(无):" + needExecute);
// 模拟10秒后仅演示逻辑实际需定时轮询
long after10s = now + 10;
needExecute = (Set<String>) jedis.zrangeByScore(delayQueueKey, 0, after10s, 0, 10);
System.out.println("10秒后需要执行的延迟任务" + needExecute);
// 执行任务后删除(避免重复执行)
for (String task : needExecute) {
jedis.zrem(delayQueueKey, task);
System.out.println("执行并删除延迟任务:" + task);
}
// ==================== 场景3带权重的用户推荐按权重排序 ====================
String recommendKey = "recommend:user:1001"; // 给用户1001的推荐列表
// score=推荐权重(越高越优先)
jedis.zadd(recommendKey, 95, "商品A高转化");
jedis.zadd(recommendKey, 80, "商品B高浏览");
jedis.zadd(recommendKey, 60, "商品C相关推荐");
System.out.println("\n用户1001的推荐列表按权重降序");
// 取TOP2推荐商品
Set<String> top2Recommend = (Set<String>) jedis.zrevrange(recommendKey, 0, 1);
System.out.println("TOP2推荐" + top2Recommend);
} catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭连接
if (jedis != null) {
jedis.close();
System.out.println("\nRedis 连接已关闭");
} }
} }
// 4. 关闭线程池,释放资源
((ExecutorService) httpClient.executor().get()).shutdown();
System.out.println("\n===== 30次请求发送完成 =====");
} }
} }