From 13fbd2d9fdc7146cc5709b30b3f04e81c829f86f Mon Sep 17 00:00:00 2001
From: cl <1442464845@qq.com>
Date: 星期二, 24 三月 2026 16:53:21 +0800
Subject: [PATCH] 大屏接口
---
src/main/java/com/zy/common/utils/RedisUtil.java | 252 +++++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 237 insertions(+), 15 deletions(-)
diff --git a/src/main/java/com/zy/common/utils/RedisUtil.java b/src/main/java/com/zy/common/utils/RedisUtil.java
index b2df114..02e3278 100644
--- a/src/main/java/com/zy/common/utils/RedisUtil.java
+++ b/src/main/java/com/zy/common/utils/RedisUtil.java
@@ -1,25 +1,49 @@
package com.zy.common.utils;
+import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
+import java.util.regex.Pattern;
/**
* redisTemplate灏佽
*
*/
-//@Component
+@Slf4j
+@Component
public class RedisUtil {
- @Autowired
- private RedisTemplate<String, Object> redisTemplate;
+ private static final long LOCAL_NO_EXPIRE = Long.MAX_VALUE;
+ /** 鏃� TTL 鍐欏叆 Redis 澶辫触鏃讹紝鍐呭瓨鏉$洰榛樿淇濈暀鏃堕暱锛堢锛� */
+ private static final long LOCAL_DEFAULT_TTL_SEC = 86400L;
- public RedisUtil(RedisTemplate<String, Object> redisTemplate) {
+// @Autowired
+// private RedisTemplate<String, Object> redisTemplate;
+
+ @Autowired
+ private RedisTemplate redisTemplate;
+
+ private final ConcurrentHashMap<String, LocalCacheEntry> localCache = new ConcurrentHashMap<>();
+ private final Object fallbackLock = new Object();
+ private volatile boolean redisFallbackMode = false;
+ private final Set<String> fallbackLocalKeys = ConcurrentHashMap.newKeySet();
+
+ public RedisTemplate getRedisTemplate() {
+ return redisTemplate;
+ }
+
+ public RedisUtil(RedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
}
@@ -63,7 +87,7 @@
return redisTemplate.hasKey(key);
} catch (Exception e) {
e.printStackTrace();
- return false;
+ return localHasValid(key);
}
}
@@ -75,10 +99,19 @@
@SuppressWarnings("unchecked")
public void del(String... key) {
if (key != null && key.length > 0) {
- if (key.length == 1) {
- redisTemplate.delete(key[0]);
- } else {
- redisTemplate.delete(CollectionUtils.arrayToList(key));
+ try {
+ if (key.length == 1) {
+ redisTemplate.delete(key[0]);
+ } else {
+ redisTemplate.delete(CollectionUtils.arrayToList(key));
+ }
+ } catch (Exception e) {
+ // Redis 涓嶅彲鐢ㄦ椂浠嶆竻鐞嗘湰鍦版潯鐩�
+ }
+ for (String k : key) {
+ if (k != null) {
+ localCache.remove(k);
+ }
}
}
}
@@ -92,7 +125,33 @@
* @return 鍊�
*/
public Object get(String key) {
- return key == null ? null : redisTemplate.opsForValue().get(key);
+ if (key == null) {
+ return null;
+ }
+ try {
+ Object v = redisTemplate.opsForValue().get(key);
+ notifyRedisAvailable();
+ return v;
+ } catch (Exception e) {
+ enterFallbackIfNeeded();
+ log.info("Redis 涓嶅彲鐢紝浠� JVM 鍐呭瓨璇诲彇 key={}锛屽師鍥�: {}", key, e.getMessage());
+ return localGet(key);
+ }
+ }
+
+ /**
+ * 鑾峰彇鍏ㄩ儴鏁版嵁
+ * @return
+ */
+ public HashMap<Object, Object> getRedis() {
+ Set<String> keys = redisTemplate.keys("*");
+ HashMap<Object, Object> map = new HashMap<>();
+ for (String key : keys) {
+ Object value = redisTemplate.opsForValue().get(key);
+ map.put(key, value);
+ }
+
+ return map;//杩斿洖鍏ㄩ儴鏁版嵁闆嗗悎
}
/**
@@ -105,10 +164,44 @@
public boolean set(String key, Object value) {
try {
redisTemplate.opsForValue().set(key, value);
+ long start = System.currentTimeMillis();
+ while (System.currentTimeMillis() - start < 10000) {//鏈夋晥鏈�10s
+ Object o = redisTemplate.opsForValue().get(key);
+ if (o == null) {
+ continue;
+ }
+
+ if (o.equals(value)) {
+ break;
+ }
+ }
+ localCache.remove(key);
+ notifyRedisAvailable();
return true;
} catch (Exception e) {
- e.printStackTrace();
- return false;
+ log.debug("Redis set 澶辫触", e);
+ localPutFallback(key, value, LOCAL_DEFAULT_TTL_SEC);
+ return true;
+ }
+ }
+
+ /**
+ * 鏅�氱紦瀛樻斁鍏�-寮傛
+ *
+ * @param key 閿�
+ * @param value 鍊�
+ * @return true鎴愬姛 false澶辫触
+ */
+ public boolean setAsync(String key, Object value) {
+ try {
+ redisTemplate.opsForValue().set(key, value);
+ localCache.remove(key);
+ notifyRedisAvailable();
+ return true;
+ } catch (Exception e) {
+ log.debug("Redis setAsync 澶辫触", e);
+ localPutFallback(key, value, LOCAL_DEFAULT_TTL_SEC);
+ return true;
}
}
@@ -126,11 +219,16 @@
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
} else {
set(key, value);
+ return true;
}
+ localCache.remove(key);
+ notifyRedisAvailable();
return true;
} catch (Exception e) {
- e.printStackTrace();
- return false;
+ log.debug("Redis set(expire) 澶辫触", e);
+ long ttl = time > 0 ? time : LOCAL_DEFAULT_TTL_SEC;
+ localPutFallback(key, value, ttl);
+ return true;
}
}
@@ -578,7 +676,15 @@
* @return
*/
public Set keys(String pattern) {
- return redisTemplate.keys(pattern);
+ try {
+ Set<?> s = redisTemplate.keys(pattern);
+ notifyRedisAvailable();
+ return s;
+ } catch (Exception e) {
+ enterFallbackIfNeeded();
+ log.info("Redis 涓嶅彲鐢紝浠� JVM 鍐呭瓨鍖归厤 keys锛宲attern={}锛屽師鍥�: {}", pattern, e.getMessage());
+ return localKeysMatching(pattern);
+ }
}
/**
@@ -591,6 +697,122 @@
redisTemplate.convertAndSend(channel, message);
}
+ private void enterFallbackIfNeeded() {
+ synchronized (fallbackLock) {
+ if (!redisFallbackMode) {
+ redisFallbackMode = true;
+ log.warn("Redis 涓嶅彲鐢紝瀛楃涓茬浉鍏崇紦瀛樺皢鏆傚瓨浜� JVM 鍐呭瓨锛屽緟 Redis 鎭㈠鍚庤嚜鍔ㄥ垏鍥� Redis 骞舵竻鐞嗕笂杩伴敭");
+ }
+ }
+ }
+
+ private void notifyRedisAvailable() {
+ if (!redisFallbackMode && fallbackLocalKeys.isEmpty()) {
+ return;
+ }
+ synchronized (fallbackLock) {
+ if (!redisFallbackMode && fallbackLocalKeys.isEmpty()) {
+ return;
+ }
+ int n = fallbackLocalKeys.size();
+ for (String k : new ArrayList<>(fallbackLocalKeys)) {
+ localCache.remove(k);
+ }
+ fallbackLocalKeys.clear();
+ redisFallbackMode = false;
+ if (n > 0) {
+ log.info("Redis 宸叉仮澶嶏紝宸叉竻鐞� JVM 鍐呭瓨涓� {} 涓洜 Redis 涓嶅彲鐢ㄨ�屾殏瀛樼殑閿�", n);
+ } else {
+ log.info("Redis 宸叉仮澶�");
+ }
+ }
+ }
+
+ private void localPutFallback(String key, Object value, long ttlSeconds) {
+ if (key == null) {
+ return;
+ }
+ synchronized (fallbackLock) {
+ if (!redisFallbackMode) {
+ redisFallbackMode = true;
+ log.warn("Redis 涓嶅彲鐢紝瀛楃涓茬浉鍏崇紦瀛樺皢鏆傚瓨浜� JVM 鍐呭瓨锛屽緟 Redis 鎭㈠鍚庤嚜鍔ㄥ垏鍥� Redis 骞舵竻鐞嗕笂杩伴敭");
+ }
+ fallbackLocalKeys.add(key);
+ localPut(key, value, ttlSeconds);
+ }
+ log.info("Redis 涓嶅彲鐢紝閿凡鍐欏叆 JVM 鍐呭瓨: {}", key);
+ }
+
+ private void localPut(String key, Object value, long ttlSeconds) {
+ if (key == null) {
+ return;
+ }
+ long expireAt = ttlSeconds > 0
+ ? System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(ttlSeconds)
+ : LOCAL_NO_EXPIRE;
+ localCache.put(key, new LocalCacheEntry(value, expireAt));
+ }
+
+ private Object localGet(String key) {
+ LocalCacheEntry e = localCache.get(key);
+ if (e == null) {
+ return null;
+ }
+ if (e.expireAtMillis != LOCAL_NO_EXPIRE && System.currentTimeMillis() > e.expireAtMillis) {
+ localCache.remove(key, e);
+ return null;
+ }
+ return e.value;
+ }
+
+ private boolean localHasValid(String key) {
+ return localGet(key) != null;
+ }
+
+ private Set<String> localKeysMatching(String pattern) {
+ if (pattern == null) {
+ return new HashSet<>();
+ }
+ Pattern p = Pattern.compile(globToRegex(pattern));
+ Set<String> out = new HashSet<>();
+ for (String k : localCache.keySet()) {
+ if (localGet(k) == null) {
+ continue;
+ }
+ if (p.matcher(k).matches()) {
+ out.add(k);
+ }
+ }
+ return out;
+ }
+
+ private static String globToRegex(String glob) {
+ StringBuilder sb = new StringBuilder("^");
+ for (int i = 0; i < glob.length(); i++) {
+ char c = glob.charAt(i);
+ if (c == '*') {
+ sb.append(".*");
+ } else if (c == '?') {
+ sb.append('.');
+ } else if ("\\.[]{}()+-^$|".indexOf(c) >= 0) {
+ sb.append('\\').append(c);
+ } else {
+ sb.append(c);
+ }
+ }
+ sb.append('$');
+ return sb.toString();
+ }
+
+ private static final class LocalCacheEntry {
+ final Object value;
+ final long expireAtMillis;
+
+ LocalCacheEntry(Object value, long expireAtMillis) {
+ this.value = value;
+ this.expireAtMillis = expireAtMillis;
+ }
+ }
}
--
Gitblit v1.9.1