diff --git a/request-test/pom.xml b/request-test/pom.xml
index 8b2162a..2599c49 100644
--- a/request-test/pom.xml
+++ b/request-test/pom.xml
@@ -19,10 +19,14 @@
- junit
- junit
- 3.8.1
- test
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ redis.clients
+ jedis
+ 4.4.6
diff --git a/request-test/src/main/java/cn/mayiming/App.java b/request-test/src/main/java/cn/mayiming/App.java
index ea2ecbe..c57914e 100644
--- a/request-test/src/main/java/cn/mayiming/App.java
+++ b/request-test/src/main/java/cn/mayiming/App.java
@@ -1,10 +1,15 @@
package cn.mayiming;
+import redis.clients.jedis.Jedis;
+
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
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.Executors;
import java.util.concurrent.TimeUnit;
@@ -15,64 +20,97 @@ import java.util.concurrent.TimeUnit;
*/
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) {
- // 1. 创建HttpClient实例(设置超时时间10秒)
- HttpClient httpClient = HttpClient.newBuilder()
- .connectTimeout(Duration.ofSeconds(10))
- .executor(Executors.newFixedThreadPool(5)) // 线程池,控制并发数
- .build();
+ Jedis jedis = null;
+ try {
+ // 建立 Redis 连接
+ jedis = new Jedis("localhost", 6379);
+ // 可选:Redis 密码认证
+ // jedis.auth("你的Redis密码");
- // 2. 循环发送30次请求
- for (int i = 1; i <= TOTAL_REQUESTS; i++) {
- int requestNum = i; // 内部类引用需要final,所以定义临时变量
- try {
- // 构建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();
+ // ==================== ZSet 结构核心操作 ====================
+ // ZSet 特点:有序、元素唯一(member 不重复)、每个元素关联一个分数(score),按score排序
+ // 场景1:商品销量排行榜(按销量从高到低排序)
+ String salesRankKey = "rank:product:sales"; // 商品销量排行榜
- // 发送请求并获取响应
- HttpResponse response = httpClient.send(
- request,
- HttpResponse.BodyHandlers.ofString()
- );
+ // 方式1:添加元素(member=商品ID,score=销量,重复添加会更新score)
+ jedis.zadd(salesRankKey, 500, "product1001"); // 商品1001销量500
+ jedis.zadd(salesRankKey, 800, "product1002"); // 商品1002销量800
+ jedis.zadd(salesRankKey, 1200, "product1003");// 商品1003销量1200
+ jedis.zadd(salesRankKey, 800, "product1002");// 重复添加,仅更新score(这里score不变)
+ System.out.println("商品销量排行榜初始化完成");
- // 3. 解析响应结果,判断是否成功
- int statusCode = response.statusCode();
- boolean isSuccess = statusCode >= 200 && statusCode < 300;
+ // 方式2:按score升序/降序查询(核心!排行榜核心操作)
+ // zrange:升序查询(0=第1名,-1=最后1名),WITHSCORES 显示分数
+ Set ascRank = (Set) jedis.zrange(salesRankKey, 0, -1);
+ System.out.println("\n销量升序排行榜(商品ID:销量):" + ascRank);
- // 打印请求结果
- System.out.printf("第 %d 次请求:%s | 状态码:%d | 响应体:%s%n",
- requestNum,
- isSuccess ? "成功" : "失败",
- statusCode,
- response.body().length() > 200 ? response.body().substring(0, 200) + "..." : response.body()
- );
+ // zrevrange:降序查询(最常用,排行榜从高到低)
+ Set descRank = (Set) jedis.zrevrange(salesRankKey, 0, -1);
+ System.out.println("销量降序排行榜(商品ID:销量):" + descRank);
- // 可选:每次请求后短暂休眠,避免压垮网关(可根据需要调整)
- TimeUnit.MILLISECONDS.sleep(100);
+ // 方式3:查询指定元素的分数(查看单个商品销量)
+ Double sales1002 = jedis.zscore(salesRankKey, "product1002");
+ System.out.println("商品1002的销量:" + sales1002);
- } catch (Exception e) {
- // 捕获所有异常,标记请求失败
- System.out.printf("第 %d 次请求:失败 | 异常信息:%s%n",
- requestNum,
- e.getMessage()
- );
+ // 方式4:更新元素分数(销量增加,比如商品1001新增200单)
+ jedis.zincrby(salesRankKey, 200, "product1001"); // score += 200
+ System.out.println("商品1001销量+200后:" + jedis.zscore(salesRankKey, "product1001"));
+
+ // 方式5:查询元素排名(降序,从0开始计数)
+ Long rank1003 = jedis.zrevrank(salesRankKey, "product1003");
+ System.out.println("商品1003的销量排名(第1名=0):" + (rank1003 + 1) + "名");
+
+ // 方式6:按分数范围查询(比如销量≥800的商品)
+ Set highSales = (Set) 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, "订单1001:10秒后自动取消"); // 10秒后处理
+ jedis.zadd(delayQueueKey, now + 30, "订单1002:30秒后自动确认收货"); // 30秒后处理
+ System.out.println("\n延迟队列初始化完成,当前时间戳:" + now);
+
+ // 方式7:获取需要执行的任务(score ≤ 当前时间戳的元素)
+ Set needExecute = (Set) jedis.zrangeByScore(delayQueueKey, 0, now, 0, 10); // 取前10个待执行任务
+ System.out.println("当前需要执行的延迟任务(无):" + needExecute);
+
+ // 模拟10秒后(仅演示逻辑,实际需定时轮询)
+ long after10s = now + 10;
+ needExecute = (Set) 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 top2Recommend = (Set) 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次请求发送完成 =====");
}
}