| | |
| | | @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)); |
| | | }); |
| | | } |
| | | |
| | | // 为已存在的key设置过期时间 - 秒 |
| | | 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); |
| | | } |
| | | } |
| | | // 为已存在的key设置过期时间 - 秒 |
| | | public void setExpire(String flag, String key, int seconds) { |
| | | executeVoid(jedis -> jedis.expire((flag + LINK + key).getBytes(), seconds)); |
| | | } |
| | | |
| | | // 为已存在的key设置过期时间 - 具体到时间戳 (秒) |
| | | 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); |
| | | } |
| | | } |
| | | // 为已存在的key设置过期时间 - 具体到时间戳 (秒) |
| | | 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; |
| | | } |
| | | } |
| | | |