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