From d7fd9123c3e100e5fc8079fea8d9cacf8afd4a32 Mon Sep 17 00:00:00 2001
From: liujie <1793218484@qq.com>
Date: 星期三, 26 八月 2026 09:29:06 +0800
Subject: [PATCH] update
---
cloud-server-account/src/main/java/com/dsh/account/util/RedisUtil.java | 80 ++++++++++++++++++++++++++++++++++++++++
1 files changed, 80 insertions(+), 0 deletions(-)
diff --git a/cloud-server-account/src/main/java/com/dsh/account/util/RedisUtil.java b/cloud-server-account/src/main/java/com/dsh/account/util/RedisUtil.java
index 8fc0825..afe45ca 100644
--- a/cloud-server-account/src/main/java/com/dsh/account/util/RedisUtil.java
+++ b/cloud-server-account/src/main/java/com/dsh/account/util/RedisUtil.java
@@ -9,6 +9,8 @@
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
@@ -73,6 +75,84 @@
/**
+ * 仅当key不存在时写入,并设置过期时间。
+ *
+ * @param key key
+ * @param value value
+ * @param time 过期时间,单位:秒
+ * @return 是否写入成功
+ */
+ public boolean setIfAbsent(String key, String value, int time) {
+ if (StringUtil.isEmpty(key)) {
+ return false;
+ }
+ try (Jedis resource = jedisPool.getResource()) {
+ return "OK".equals(resource.set(key, value, "NX", "EX", time));
+ }
+ }
+
+
+ /**
+ * 原子比较并删除。key存在时无论是否匹配都会被删除,避免验证码被暴力枚举。
+ */
+ public boolean consumeIfEquals(String key, String expectedValue) {
+ if (StringUtil.isEmpty(key) || expectedValue == null) {
+ return false;
+ }
+ String script = "local value = redis.call('get', KEYS[1]); "
+ + "if not value then return 0 end; "
+ + "redis.call('del', KEYS[1]); "
+ + "if value == ARGV[1] then return 1 else return 0 end";
+ try (Jedis resource = jedisPool.getResource()) {
+ Object result = resource.eval(
+ script,
+ Collections.singletonList(key),
+ Collections.singletonList(expectedValue)
+ );
+ return Long.valueOf(1L).equals(result);
+ }
+ }
+
+
+ /**
+ * 获取固定时间窗口内的一个名额。
+ */
+ public boolean tryAcquireFixedWindow(String key, int maxCount, int windowSeconds) {
+ if (StringUtil.isEmpty(key) || maxCount <= 0 || windowSeconds <= 0) {
+ return false;
+ }
+ String script = "local current = tonumber(redis.call('get', KEYS[1]) or '0'); "
+ + "if current >= tonumber(ARGV[2]) then return 0 end; "
+ + "current = redis.call('incr', KEYS[1]); "
+ + "if current == 1 then redis.call('expire', KEYS[1], ARGV[1]) end; return 1";
+ try (Jedis resource = jedisPool.getResource()) {
+ Object result = resource.eval(
+ script,
+ Collections.singletonList(key),
+ Arrays.asList(String.valueOf(windowSeconds), String.valueOf(maxCount))
+ );
+ return Long.valueOf(1L).equals(result);
+ }
+ }
+
+
+ /**
+ * 释放固定时间窗口内已获取的名额,用于下游调用失败后的补偿。
+ */
+ public void releaseFixedWindow(String key) {
+ if (StringUtil.isEmpty(key)) {
+ return;
+ }
+ String script = "local current = tonumber(redis.call('get', KEYS[1]) or '0'); "
+ + "if current <= 1 then redis.call('del', KEYS[1]); "
+ + "else redis.call('decr', KEYS[1]); end; return 1";
+ try (Jedis resource = jedisPool.getResource()) {
+ resource.eval(script, Collections.singletonList(key), Collections.<String>emptyList());
+ }
+ }
+
+
+ /**
* 批量获取
*
* @param kes
--
Gitblit v1.7.1