From 464116335cba47ddce55ee3a4ddc87af7fee5d15 Mon Sep 17 00:00:00 2001
From: zhou zhou <3272660260@qq.com>
Date: 星期四, 09 四月 2026 17:08:23 +0800
Subject: [PATCH] #redis降级

---
 rsf-server/src/main/java/com/vincent/rsf/server/common/service/RedisService.java |  674 +++++++++++++++++++++-----------------------------------
 1 files changed, 252 insertions(+), 422 deletions(-)

diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/common/service/RedisService.java b/rsf-server/src/main/java/com/vincent/rsf/server/common/service/RedisService.java
index d6c0af5..95b6d68 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/common/service/RedisService.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/common/service/RedisService.java
@@ -20,473 +20,303 @@
 @Service
 public class RedisService {
 
-	private static final String LINK = ".";
+    private static final String LINK = ".";
+    private static final long MIN_DEGRADE_WINDOW_MS = 30000L;
 
-	protected JedisPool pool;
+    protected volatile JedisPool pool;
 
-	Integer index = 0;
+    Integer index = 0;
 
-	public Boolean initialize = true;
+    public volatile Boolean initialize = true;
 
-	@Autowired
-	private RedisProperties redisProperties;
+    private volatile long degradedUntilMillis = 0L;
 
-	public JedisPool getPool() {
-		if (null == this.pool) {
-			JedisPoolConfig config = new JedisPoolConfig();
-			config.setTestOnBorrow(false);
-			this.index = redisProperties.getIndex();
-			this.pool = new JedisPool(config
-					, redisProperties.getHost()
-					, redisProperties.getPort()
-					, redisProperties.getTimeout()
-					, redisProperties.getPassword()
-			);
-		}
-		return this.pool;
-	}
+    @Autowired
+    private RedisProperties redisProperties;
 
-	public Jedis getJedis(){
-		try{
-			Jedis jedis = this.getPool().getResource();
+    public synchronized JedisPool getPool() {
+        if (this.pool == null) {
+            JedisPoolConfig config = new JedisPoolConfig();
+            config.setTestOnBorrow(false);
+            this.index = redisProperties.getIndex();
+            this.pool = new JedisPool(config,
+                    redisProperties.getHost(),
+                    redisProperties.getPort(),
+                    redisProperties.getTimeout(),
+                    redisProperties.getPassword()
+            );
+        }
+        return this.pool;
+    }
 
-			if(this.index != jedis.getDB()) {
-				jedis.select(this.index);
-			}
-			return jedis;
-		} catch (Exception e){
-			log.error(this.getClass().getSimpleName(), e);
-		}
-		return null;
-	}
+    public Jedis getJedis() {
+        if (isDegradedNow()) {
+            return null;
+        }
+        try {
+            Jedis jedis = this.getPool().getResource();
+            if (this.index != jedis.getDB()) {
+                jedis.select(this.index);
+            }
+            markRecovered();
+            return jedis;
+        } catch (Exception e) {
+            markUnavailable(e);
+        }
+        return null;
+    }
 
-	// key - object ----------------------------------------------------------------------------------------------------------
+    // key - object ----------------------------------------------------------------------------------------------------------
 
-	public String set(String flag, String key, Object value) {
-		if(!this.initialize) {
-			return null;
-		}
-		if(null == value) {
-			this.delete(flag, key);
-			return null;
-		}
-		Jedis jedis = this.getJedis();
-		try{
-			return jedis.set((flag + LINK + key).getBytes(), Serialize.serialize(value));
-		} catch (Exception e) {
-			log.error(this.getClass().getSimpleName(), e);
-		}
-		return null;
-	}
+    public String set(String flag, String key, Object value) {
+        if (value == null) {
+            this.delete(flag, key);
+            return null;
+        }
+        return execute(null, jedis -> jedis.set((flag + LINK + key).getBytes(), Serialize.serialize(value)));
+    }
 
-	public String set(String flag, String key, Object value, Integer seconds) {
-		if(!this.initialize) {
-			return null;
-		}
-		if (null == value) {
-			this.delete(flag, key);
-			return null;
-		}
-		Jedis jedis = this.getJedis();
-		try{
-			return jedis.setex((flag + LINK + key).getBytes(), seconds, Serialize.serialize(value));
-		} catch (Exception e) {
-			log.error(this.getClass().getSimpleName(), e);
-		}
-		return null;
-	}
+    public String set(String flag, String key, Object value, Integer seconds) {
+        if (value == null) {
+            this.delete(flag, key);
+            return null;
+        }
+        return execute(null, jedis -> jedis.setex((flag + LINK + key).getBytes(), seconds, Serialize.serialize(value)));
+    }
 
-	public <T> T get(String flag, String key) {
-		if(!this.initialize) {
-			return null;
-		}
-		Jedis jedis = this.getJedis();
-		try{
-			byte[] bytes = jedis.get((flag + LINK + key).getBytes());
-			if(bytes == null || bytes.length == 0 ) {
-				return null;
-			}
-			return (T) Serialize.unSerialize(bytes);
-		} catch (Exception e) {
-			log.error(this.getClass().getSimpleName(), e);
-		}
-		return null;
-	}
+    public <T> T get(String flag, String key) {
+        return execute(null, jedis -> {
+            byte[] bytes = jedis.get((flag + LINK + key).getBytes());
+            if (bytes == null || bytes.length == 0) {
+                return null;
+            }
+            return (T) Serialize.unSerialize(bytes);
+        });
+    }
 
-	public Long delete(String flag, String key) {
-		if(!this.initialize) {
-			return null;
-		}
-		Jedis jedis = this.getJedis();
-		try{
-			return jedis.del((flag + LINK + key).getBytes());
-		} catch (Exception e) {
-			log.error(this.getClass().getSimpleName(), e);
-		}
-		return null;
-	}
+    public Long delete(String flag, String key) {
+        return execute(null, jedis -> jedis.del((flag + LINK + key).getBytes()));
+    }
 
-	public Long clear(String flag) {
-		if(!this.initialize) {
-			return null;
-		}
-		Jedis jedis = this.getJedis();
-		this.setValue(flag, "CLEARING", "true");
-		try{
-			Object returnValue = jedis.eval("local keys = redis.call('keys', ARGV[1]) for i=1,#keys,1000 do redis.call('del', unpack(keys, i, math.min(i+4999, #keys))) end return #keys",0,flag + LINK + "*");
-			return Long.parseLong(String.valueOf(returnValue));
-		} catch (Exception e) {
-			log.error(this.getClass().getSimpleName(), e);
-		}
-		return null;
-	}
+    public Long clear(String flag) {
+        this.setValue(flag, "CLEARING", "true");
+        return execute(null, jedis -> {
+            Object returnValue = jedis.eval("local keys = redis.call('keys', ARGV[1]) for i=1,#keys,1000 do redis.call('del', unpack(keys, i, math.min(i+4999, #keys))) end return #keys", 0, flag + LINK + "*");
+            return Long.parseLong(String.valueOf(returnValue));
+        });
+    }
 
-	// 涓哄凡瀛樺湪鐨刱ey璁剧疆杩囨湡鏃堕棿 - 绉�
-	public void setExpire(String flag, String key, int seconds){
-		if(!this.initialize) {
-			return;
-		}
-		Jedis jedis = this.getJedis();
-		try{
-			jedis.expire((flag + LINK + key).getBytes(), seconds);
-		} catch (Exception e) {
-			log.error(this.getClass().getSimpleName(), e);
-		}
-	}
+    // 涓哄凡瀛樺湪鐨刱ey璁剧疆杩囨湡鏃堕棿 - 绉�
+    public void setExpire(String flag, String key, int seconds) {
+        executeVoid(jedis -> jedis.expire((flag + LINK + key).getBytes(), seconds));
+    }
 
-	// 涓哄凡瀛樺湪鐨刱ey璁剧疆杩囨湡鏃堕棿 - 鍏蜂綋鍒版椂闂存埑 锛堢锛�
-	public void setExpireAt(String flag, String key, Date toTime){
-		if(!this.initialize) {
-			return;
-		}
-		Jedis jedis = this.getJedis();
-		try{
-			jedis.expireAt((flag + LINK + key).getBytes(), toTime.getTime()/1000);
-		} catch (Exception e) {
-			log.error(this.getClass().getSimpleName(), e);
-		}
-	}
+    // 涓哄凡瀛樺湪鐨刱ey璁剧疆杩囨湡鏃堕棿 - 鍏蜂綋鍒版椂闂存埑 锛堢锛�
+    public void setExpireAt(String flag, String key, Date toTime) {
+        executeVoid(jedis -> jedis.expireAt((flag + LINK + key).getBytes(), toTime.getTime() / 1000));
+    }
 
-	// 鑾峰彇杩囨湡鍓╀綑鏃堕棿锛堢锛� ttl == -1 娌℃湁璁剧疆杩囨湡鏃堕棿锛� ttl == -2 key涓嶅瓨鍦�
-	public Long getExpire(String flag, String key) {
-		if(!this.initialize) {
-			return null;
-		}
-		Jedis jedis = this.getJedis();
-		try{
-			return jedis.ttl((flag + LINK + key).getBytes());
-		} catch (Exception e) {
-			log.error(this.getClass().getSimpleName(), e);
-		}
-		return null;
-	}
+    // 鑾峰彇杩囨湡鍓╀綑鏃堕棿锛堢锛� ttl == -1 娌℃湁璁剧疆杩囨湡鏃堕棿锛� ttl == -2 key涓嶅瓨鍦�
+    public Long getExpire(String flag, String key) {
+        return execute(null, jedis -> jedis.ttl((flag + LINK + key).getBytes()));
+    }
 
 
-	// key - string ----------------------------------------------------------------------------------------------------------
+    // key - string ----------------------------------------------------------------------------------------------------------
 
-	public String setValue(String flag, String key, String value) {
-		if(!this.initialize) {
-			return null;
-		}
-		Jedis jedis = this.getJedis();
-		try{
-			return jedis.set(flag + LINK + key, value);
-		} catch (Exception e) {
-			log.error(this.getClass().getSimpleName(), e);
-		}
-		return null;
-	}
+    public String setValue(String flag, String key, String value) {
+        return execute(null, jedis -> jedis.set(flag + LINK + key, value));
+    }
 
-	public String setValue(String flag, String key, String value, Integer seconds) {
-		if(!this.initialize) {
-			return null;
-		}
-		Jedis jedis = this.getJedis();
-		try{
-			return jedis.setex(flag + LINK + key, seconds , value);
-		} catch (Exception e) {
-			log.error(this.getClass().getSimpleName(), e);
-		}
-		return null;
-	}
+    public String setValue(String flag, String key, String value, Integer seconds) {
+        return execute(null, jedis -> jedis.setex(flag + LINK + key, seconds, value));
+    }
 
-	public String getValue(String flag, String key) {
-		if(!this.initialize) {
-			return null;
-		}
-		Jedis jedis = this.getJedis();
-		try{
-			return jedis.get(flag + LINK + key);
-		} catch (Exception e) {
-			log.error(this.getClass().getSimpleName(), e);
-		}
-		return null;
-	}
+    public String getValue(String flag, String key) {
+        return execute(null, jedis -> jedis.get(flag + LINK + key));
+    }
 
-	public Long deleteValue(String flag, String... key) {
-		if(!this.initialize) {
-			return null;
-		}
+    public Long deleteValue(String flag, String... key) {
+        return execute(null, jedis -> {
+            String[] keys = new String[key.length];
+            for (int i = 0; i < key.length; i++) {
+                keys[i] = flag + LINK + key[i];
+            }
+            return jedis.del(keys);
+        });
+    }
 
-		Jedis jedis = this.getJedis();
-		try{
-			String[] keys = new String[key.length];
-			for(int i=0;i<key.length;i++){
-				keys[i] = flag + LINK + key[i];
-			}
-			return jedis.del(keys);
-		} catch (Exception e) {
-			log.error(this.getClass().getSimpleName(), e);
-		}
-		return null;
-	}
+    public Long clearValue(String flag) {
+        this.setValue(flag, "CLEARING", "true");
+        return execute(null, jedis -> {
+            Object returnValue = jedis.eval("return redis.call('del', unpack(redis.call('keys', ARGV[1])))", 0, flag + LINK + "*");
+            return Long.parseLong(String.valueOf(returnValue));
+        });
+    }
 
-	public Long clearValue(String flag) {
-		if(!this.initialize) {
-			return null;
-		}
+    public void setValueExpire(String flag, String key, int seconds) {
+        executeVoid(jedis -> jedis.expire((flag + LINK + key).getBytes(), seconds));
+    }
 
-		this.setValue(flag, "CLEARING", "true");
-		Jedis jedis = this.getJedis();
-
-		try{
-			Object returnValue = jedis.eval("return redis.call('del', unpack(redis.call('keys', ARGV[1])))",0,flag + LINK + "*");
-			return Long.parseLong(String.valueOf(returnValue));
-		} catch (Exception e) {
-			log.error(this.getClass().getSimpleName(), e);
-		}
-		return null;
-	}
-
-	public void setValueExpire(String flag, String key,int seconds){
-		if(!this.initialize) {
-			return;
-		}
-		Jedis jedis = this.getJedis();
-		try{
-			jedis.expire((flag + LINK + key).getBytes(), seconds);
-		} catch (Exception e) {
-			log.error(this.getClass().getSimpleName(), e);
-		}
-	}
-
-	public void setValueExpireAt(String flag, String key,Date atTime){
-		if(!this.initialize) {
-			return;
-		}
-		Jedis jedis = this.getJedis();
-		try{
-			jedis.expireAt((flag + LINK + key).getBytes(), atTime.getTime()/1000);
-		} catch (Exception e) {
-			log.error(this.getClass().getSimpleName(), e);
-		}
-	}
+    public void setValueExpireAt(String flag, String key, Date atTime) {
+        executeVoid(jedis -> jedis.expireAt((flag + LINK + key).getBytes(), atTime.getTime() / 1000));
+    }
 
 
-	// hash ----------------------------------------------------------------------------------------------------------
+    // hash ----------------------------------------------------------------------------------------------------------
 
-	public Long setMap(String name, String key, Object value) {
-		if(!this.initialize) {
-			return null;
-		}
-		if(value == null){
-			deleteMap(name,key);
-			return null;
-		}
-		Jedis jedis = this.getJedis();
-		try {
-			return jedis.hset(name.getBytes(), key.getBytes(), Serialize.serialize(value));
-		} catch (Exception e) {
-			log.error(this.getClass().getSimpleName(), e);
-		}
-		return null;
-	}
+    public Long setMap(String name, String key, Object value) {
+        if (value == null) {
+            deleteMap(name, key);
+            return null;
+        }
+        return execute(null, jedis -> jedis.hset(name.getBytes(), key.getBytes(), Serialize.serialize(value)));
+    }
 
-	public <T> T getMap(String name, String key) {
-		if(!this.initialize) {
-			return null;
-		}
-		Jedis jedis = this.getJedis();
-		try{
-			byte[] bytes = jedis.hget(name.getBytes(), key.getBytes());
-			if (bytes == null || bytes.length == 0) {
-				return null;
-			}
-			return (T) Serialize.unSerialize(bytes);
-		} catch (Exception e) {
-			log.error(this.getClass().getSimpleName(), e);
-		}
-		return null;
-	}
+    public <T> T getMap(String name, String key) {
+        return execute(null, jedis -> {
+            byte[] bytes = jedis.hget(name.getBytes(), key.getBytes());
+            if (bytes == null || bytes.length == 0) {
+                return null;
+            }
+            return (T) Serialize.unSerialize(bytes);
+        });
+    }
 
-	public Set<String> getMapKeys(String name) {
-		if(!this.initialize) {
-			return null;
-		}
-		Jedis jedis = this.getJedis();
-		try{
-            return jedis.hkeys(name);
-		} catch (Exception e) {
-			log.error(this.getClass().getSimpleName(), e);
-		}
-		return null;
-	}
+    public Set<String> getMapKeys(String name) {
+        return execute(null, jedis -> jedis.hkeys(name));
+    }
 
-	public Long deleteMap(String name, String... key) {
-		if(!this.initialize) {
-			return null;
-		}
-		Jedis jedis = this.getJedis();
-		try{
-			String[] keys = new String[key.length];
+    public Long deleteMap(String name, String... key) {
+        return execute(null, jedis -> {
+            String[] keys = new String[key.length];
             System.arraycopy(key, 0, keys, 0, key.length);
             return jedis.hdel(name, keys);
-		} catch (Exception e) {
-			log.error(this.getClass().getSimpleName(), e);
-		}
-		return null;
-	}
+        });
+    }
 
-	public Long clearMap(String name) {
-		if(!this.initialize) {
-			return null;
-		}
-		Jedis jedis = this.getJedis();
-		try{
-			return jedis.del(name);
-		} catch (Exception e) {
-			log.error(this.getClass().getSimpleName(), e);
-		}
-		return null;
-	}
+    public Long clearMap(String name) {
+        return execute(null, jedis -> jedis.del(name));
+    }
 
-	public void setMapExpire(String name,int seconds){
-		if(!this.initialize) {
-			return;
-		}
-		Jedis jedis = this.getJedis();
-		try{
-			jedis.expire(name.getBytes(), seconds);
-		} catch (Exception e) {
-			log.error(this.getClass().getSimpleName(), e);
-		}
-	}
+    public void setMapExpire(String name, int seconds) {
+        executeVoid(jedis -> jedis.expire(name.getBytes(), seconds));
+    }
 
-	public void setMapExpireAt(String name,Date atTime){
-		if(!this.initialize) {
-			return;
-		}
-		Jedis jedis = this.getJedis();
-		try{
-			jedis.expireAt(name.getBytes(), atTime.getTime()/1000);
-		} catch (Exception e) {
-			log.error(this.getClass().getSimpleName(), e);
-		}
-	}
+    public void setMapExpireAt(String name, Date atTime) {
+        executeVoid(jedis -> jedis.expireAt(name.getBytes(), atTime.getTime() / 1000));
+    }
 
 
-	// mq ----------------------------------------------------------------------------------------------------------
+    // mq ----------------------------------------------------------------------------------------------------------
 
-	// 鍒楄〃鏈熬娣诲姞鍏冪礌
-	public Long push(String name, Object value) {
-		if(!this.initialize) {
-			return null;
-		}
-		if(value == null){
-			return null;
-		}
-		Jedis jedis = this.getJedis();
-		try{
-			return jedis.rpush(name.getBytes(), Serialize.serialize(value));
-		} catch (Exception e) {
-			log.error(this.getClass().getSimpleName(), e);
-		}
-		return null;
-	}
+    // 鍒楄〃鏈熬娣诲姞鍏冪礌
+    public Long push(String name, Object value) {
+        if (value == null) {
+            return null;
+        }
+        return execute(null, jedis -> jedis.rpush(name.getBytes(), Serialize.serialize(value)));
+    }
 
-	// 鑾峰彇鍒楄〃澶撮儴鍏冪礌 && 鍒犻櫎
-	public <T> T pop(String name) {
-		if(!this.initialize){
-			return null;
-		}
-		Jedis jedis = this.getJedis();
-		try{
-			byte[] bytes = jedis.lpop(name.getBytes());
-			if(bytes == null || bytes.length == 0) {
-				return null;
-			}
-			return (T) Serialize.unSerialize(bytes);
-		} catch (Exception e) {
-			log.error(this.getClass().getSimpleName(), e);
-		}
-		return null;
-	}
+    // 鑾峰彇鍒楄〃澶撮儴鍏冪礌 && 鍒犻櫎
+    public <T> T pop(String name) {
+        return execute(null, jedis -> {
+            byte[] bytes = jedis.lpop(name.getBytes());
+            if (bytes == null || bytes.length == 0) {
+                return null;
+            }
+            return (T) Serialize.unSerialize(bytes);
+        });
+    }
 
-	// 鍒犻櫎
-	public Long deleteList(String name) {
-		if(!this.initialize) {
-			return null;
-		}
-		Jedis jedis = this.getJedis();
-		try{
-			return jedis.del(name);
-		} catch (Exception e) {
-			log.error(this.getClass().getSimpleName(), e);
-		}
-		return null;
-	}
+    // 鍒犻櫎
+    public Long deleteList(String name) {
+        return execute(null, jedis -> jedis.del(name));
+    }
 
-	public void setListExpire(String name, int seconds){
-		if(!this.initialize) {
-			return;
-		}
-		Jedis jedis = this.getJedis();
-		try{
-			jedis.expire(name.getBytes(), seconds);
-		} catch (Exception e) {
-			log.error(this.getClass().getSimpleName(), e);
-		}
-	}
+    public void setListExpire(String name, int seconds) {
+        executeVoid(jedis -> jedis.expire(name.getBytes(), seconds));
+    }
 
-	public void setListExpireAt(String name, Date atTime){
-		if(!this.initialize) {
-			return;
-		}
-		Jedis jedis = this.getJedis();
-		try{
-			jedis.expireAt(name.getBytes(), atTime.getTime()/1000);
-		} catch (Exception e) {
-			log.error(this.getClass().getSimpleName(), e);
-		}
-	}
+    public void setListExpireAt(String name, Date atTime) {
+        executeVoid(jedis -> jedis.expireAt(name.getBytes(), atTime.getTime() / 1000));
+    }
 
-	// count ----------------------------------------------------------------------------------------------------------
+    // count ----------------------------------------------------------------------------------------------------------
 
-	public Long incr(String key) {
-		if(!this.initialize) {
-			return null;
-		}
-		Jedis jedis = this.getJedis();
-		try{
-            return jedis.incr("COUNT." + key);
-		} catch (Exception e) {
-			log.error(this.getClass().getSimpleName(), e);
-		}
-		return null;
-	}
+    public Long incr(String key) {
+        return execute(null, jedis -> jedis.incr("COUNT." + key));
+    }
 
-	public Long decr(String key) {
-		if(!this.initialize) {
-			return null;
-		}
-		Jedis jedis = this.getJedis();
-		try{
-            return jedis.decr("COUNT." + key);
-		} catch (Exception e) {
-			log.error(this.getClass().getSimpleName(), e);
-		}
-		return null;
-	}
+    public Long decr(String key) {
+        return execute(null, jedis -> jedis.decr("COUNT." + key));
+    }
 
+    private boolean isDegradedNow() {
+        return !Boolean.TRUE.equals(this.initialize) && System.currentTimeMillis() < this.degradedUntilMillis;
+    }
+
+    private void markRecovered() {
+        if (Boolean.TRUE.equals(this.initialize)) {
+            return;
+        }
+        synchronized (this) {
+            if (Boolean.TRUE.equals(this.initialize)) {
+                return;
+            }
+            this.initialize = true;
+            this.degradedUntilMillis = 0L;
+            log.info("Redis recovered, degrade mode cleared.");
+        }
+    }
+
+    private void markUnavailable(Exception e) {
+        long now = System.currentTimeMillis();
+        long nextRetryAt = now + getDegradeWindowMillis();
+        boolean shouldLog = Boolean.TRUE.equals(this.initialize) || now >= this.degradedUntilMillis;
+        synchronized (this) {
+            this.initialize = false;
+            this.degradedUntilMillis = nextRetryAt;
+        }
+        if (shouldLog) {
+            log.warn("Redis unavailable, degrade mode enabled until {}. message={}", new Date(nextRetryAt), e.getMessage());
+        }
+    }
+
+    private long getDegradeWindowMillis() {
+        return Math.max((long) redisProperties.getTimeout() * 2L, MIN_DEGRADE_WINDOW_MS);
+    }
+
+    private <T> T execute(T fallbackValue, RedisCallback<T> callback) {
+        if (isDegradedNow()) {
+            return fallbackValue;
+        }
+        Jedis jedis = getJedis();
+        if (jedis == null) {
+            return fallbackValue;
+        }
+        try (jedis) {
+            return callback.doWithJedis(jedis);
+        } catch (Exception e) {
+            markUnavailable(e);
+            return fallbackValue;
+        }
+    }
+
+    private void executeVoid(RedisVoidCallback callback) {
+        execute(null, jedis -> {
+            callback.doWithJedis(jedis);
+            return null;
+        });
+    }
+
+    @FunctionalInterface
+    private interface RedisCallback<T> {
+        T doWithJedis(Jedis jedis) throws Exception;
+    }
+
+    @FunctionalInterface
+    private interface RedisVoidCallback {
+        void doWithJedis(Jedis jedis) throws Exception;
+    }
 }
-

--
Gitblit v1.9.1