mirror of
https://github.com/LamGC/ContentGrabbingJi.git
synced 2025-04-30 06:37:36 +00:00
[Add] 增加新的缓存库类(HotDataCacheStore, StringRedisCacheStore);
[Add] CacheStore 增加update(String, T, long)方法, 该方法将以Unix时间戳设置过期时间; [Update] LocalHashCacheStore, RedisPoolCacheStore 适配CacheStore新方法; [Delete] 删除 RedisCacheStore 类;
This commit is contained in:
parent
8375b81b17
commit
a0efc3c0af
@ -4,6 +4,14 @@ import java.util.Date;
|
|||||||
|
|
||||||
public interface CacheStore<T> {
|
public interface CacheStore<T> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新或添加缓存项
|
||||||
|
* @param key 缓存键名
|
||||||
|
* @param value 缓存值
|
||||||
|
* @param expire 有效期, 单位为ms(毫秒), 如不过期传入0或赋值
|
||||||
|
*/
|
||||||
|
void update(String key, T value, long expire);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新或添加缓存项
|
* 更新或添加缓存项
|
||||||
* @param key 缓存键名
|
* @param key 缓存键名
|
||||||
|
96
src/main/java/net/lamgc/cgj/bot/cache/HotDataCacheStore.java
vendored
Normal file
96
src/main/java/net/lamgc/cgj/bot/cache/HotDataCacheStore.java
vendored
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
package net.lamgc.cgj.bot.cache;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 具有继承性的热点数据缓存库
|
||||||
|
* @param <T> 存储类型
|
||||||
|
* @author LamGC
|
||||||
|
*/
|
||||||
|
public class HotDataCacheStore<T> implements CacheStore<T> {
|
||||||
|
|
||||||
|
private final CacheStore<T> parent;
|
||||||
|
private final CacheStore<T> current;
|
||||||
|
private final long expireTime;
|
||||||
|
private final int expireFloatRange;
|
||||||
|
private final Random random = new Random();
|
||||||
|
private final Logger log = LoggerFactory.getLogger(HotDataCacheStore.class.getSimpleName() + "@" + Integer.toHexString(this.hashCode()));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造热点缓存存储对象
|
||||||
|
* @param parent 上级缓存存储库
|
||||||
|
* @param current 热点缓存存储库, 最好使用本地缓存(例如 {@linkplain LocalHashCacheStore LocalHashCacheStore})
|
||||||
|
* @param expireTime 本地缓存库的缓存项过期时间,
|
||||||
|
* 该时间并不是所有缓存项的最终过期时间, 还需要根据expireFloatRange的设定随机设置, 公式:
|
||||||
|
* {@code expireTime + new Random().nextInt(expireFloatRange)}
|
||||||
|
* @param expireFloatRange 过期时间的浮动范围, 用于防止短时间内大量缓存项失效导致的缓存雪崩
|
||||||
|
*/
|
||||||
|
public HotDataCacheStore(CacheStore<T> parent, CacheStore<T> current, long expireTime, int expireFloatRange) {
|
||||||
|
this.parent = parent;
|
||||||
|
this.current = current;
|
||||||
|
this.expireTime = expireTime;
|
||||||
|
this.expireFloatRange = expireFloatRange;
|
||||||
|
log.debug("HotDataCacheStore初始化完成. (Parent: {}, Current: {}, expireTime: {}, expireFloatRange: {})",
|
||||||
|
parent, current, expireTime, expireFloatRange);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(String key, T value, long expire) {
|
||||||
|
update(key, value, expire <= 0 ? null : new Date(System.currentTimeMillis() + expire));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(String key, T value, Date expire) {
|
||||||
|
parent.update(key, value, expire);
|
||||||
|
current.update(key, value, expire);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T getCache(String key) {
|
||||||
|
if(!exists(key)) {
|
||||||
|
log.debug("查询缓存键名不存在, 直接返回null.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
T result = current.getCache(key);
|
||||||
|
if(Objects.isNull(result)) {
|
||||||
|
log.debug("Current缓存库未命中, 查询Parent缓存库");
|
||||||
|
T parentResult = parent.getCache(key);
|
||||||
|
if(Objects.isNull(parentResult)) {
|
||||||
|
log.debug("Parent缓存库未命中, 缓存不存在");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
log.debug("Parent缓存命中, 正在更新Current缓存库...");
|
||||||
|
current.update(key, parentResult, expireTime + random.nextInt(expireFloatRange));
|
||||||
|
log.debug("Current缓存库更新完成.");
|
||||||
|
result = parentResult;
|
||||||
|
} else {
|
||||||
|
log.debug("Current缓存库缓存命中.");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean exists(String key) {
|
||||||
|
return current.exists(key) || parent.exists(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean exists(String key, Date date) {
|
||||||
|
return current.exists(key, date) || parent.exists(key, date);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean clear() {
|
||||||
|
return current.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportedPersistence() {
|
||||||
|
return current.supportedPersistence() || parent.supportedPersistence();
|
||||||
|
}
|
||||||
|
}
|
@ -28,6 +28,11 @@ public class LocalHashCacheStore<T> implements CacheStore<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(String key, T value, long expire) {
|
||||||
|
update(key, value, expire <= 0 ? null : new Date(System.currentTimeMillis() + expire));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(String key, T value, Date expire) {
|
public void update(String key, T value, Date expire) {
|
||||||
if(cache.containsKey(key)) {
|
if(cache.containsKey(key)) {
|
||||||
|
@ -1,100 +0,0 @@
|
|||||||
package net.lamgc.cgj.bot.cache;
|
|
||||||
|
|
||||||
import com.google.common.base.Strings;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import redis.clients.jedis.Jedis;
|
|
||||||
import redis.clients.jedis.Transaction;
|
|
||||||
import redis.clients.jedis.exceptions.JedisConnectionException;
|
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
public abstract class RedisCacheStore<T> implements CacheStore<T> {
|
|
||||||
|
|
||||||
private final Jedis jedis;
|
|
||||||
private final Logger log;
|
|
||||||
private final String keyPrefix;
|
|
||||||
|
|
||||||
public RedisCacheStore(URI redisServerUri, String prefix) {
|
|
||||||
this(redisServerUri, null, prefix);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建一个Redis缓存数据库对象
|
|
||||||
* @param redisServerUri 数据库链接
|
|
||||||
* @param password 登录密码(如果有)
|
|
||||||
* @throws JedisConnectionException 当连接失败时抛出
|
|
||||||
*/
|
|
||||||
public RedisCacheStore(URI redisServerUri, String password, String prefix) throws JedisConnectionException {
|
|
||||||
this.jedis = new Jedis(redisServerUri.getHost(), redisServerUri.getPort() <= 0 ? 6379 : redisServerUri.getPort());
|
|
||||||
log = LoggerFactory.getLogger(this.getClass().getSimpleName() + "@" + Integer.toHexString(jedis.hashCode()));
|
|
||||||
log.info("Redis数据库连接状态: {}", jedis.ping());
|
|
||||||
if(password != null) {
|
|
||||||
this.jedis.auth(password);
|
|
||||||
}
|
|
||||||
if(!Strings.isNullOrEmpty(prefix)) {
|
|
||||||
keyPrefix = prefix.endsWith(".") ? prefix : prefix + ".";
|
|
||||||
} else {
|
|
||||||
keyPrefix = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void connect() {
|
|
||||||
if(!"PONE".equals(jedis.ping())) {
|
|
||||||
jedis.connect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void update(String key, T value, Date expire) {
|
|
||||||
Transaction multi = jedis.multi();
|
|
||||||
multi.set(keyPrefix + key, parse(value));
|
|
||||||
if(expire != null) {
|
|
||||||
multi.expireAt(keyPrefix + key, expire.getTime());
|
|
||||||
log.debug("已设置Key {} 的过期时间(Expire: {})", key, expire.getTime());
|
|
||||||
}
|
|
||||||
multi.exec();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public T getCache(String key) {
|
|
||||||
return analysis(jedis.get(keyPrefix + key));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean exists(String key) {
|
|
||||||
return jedis.exists(keyPrefix + key);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean exists(String key, Date date) {
|
|
||||||
return exists(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean clear() {
|
|
||||||
String result = jedis.flushDB();
|
|
||||||
log.info("flushDB返回结果: {}", result);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 转换方法
|
|
||||||
* @param dataObj 原数据
|
|
||||||
* @return 文本型数据
|
|
||||||
*/
|
|
||||||
protected abstract String parse(T dataObj);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将String数据转换成指定类型的对象
|
|
||||||
* @param dataStr String数据
|
|
||||||
* @return 泛型指定类型的对象
|
|
||||||
*/
|
|
||||||
protected abstract T analysis(String dataStr);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean supportedPersistence() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -21,15 +21,11 @@ public abstract class RedisPoolCacheStore<T> implements CacheStore<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public RedisPoolCacheStore(URI redisServerUri, JedisPoolConfig config, int timeout, String password, String prefix) {
|
public RedisPoolCacheStore(URI redisServerUri, JedisPoolConfig config, int timeout, String password, String prefix) {
|
||||||
jedisPool = new JedisPool(config == null ? new GenericObjectPoolConfig<JedisPool>() : config, redisServerUri.getHost(),
|
this(new JedisPool(config == null ? new GenericObjectPoolConfig<JedisPool>() : config, redisServerUri.getHost(),
|
||||||
redisServerUri.getPort() <= 0 ? 6379 : redisServerUri.getPort(),
|
redisServerUri.getPort() == -1 ? 6379 : redisServerUri.getPort(),
|
||||||
timeout <= 0 ? Protocol.DEFAULT_TIMEOUT : timeout, password);
|
timeout <= 0 ? Protocol.DEFAULT_TIMEOUT : timeout, password),
|
||||||
log = LoggerFactory.getLogger(this.getClass().getSimpleName() + "@" + Integer.toHexString(jedisPool.hashCode()));
|
prefix
|
||||||
if(prefix != null) {
|
);
|
||||||
keyPrefix = prefix.endsWith(".") ? prefix : prefix + ".";
|
|
||||||
} else {
|
|
||||||
keyPrefix = "";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public RedisPoolCacheStore(JedisPool pool, String keyPrefix) {
|
public RedisPoolCacheStore(JedisPool pool, String keyPrefix) {
|
||||||
@ -45,16 +41,19 @@ public abstract class RedisPoolCacheStore<T> implements CacheStore<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(String key, T value, long expire) {
|
||||||
|
update(key, value, expire <= 0 ? null : new Date(System.currentTimeMillis() + expire));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(String key, T value, Date expire) {
|
public void update(String key, T value, Date expire) {
|
||||||
Jedis jedis = jedisPool.getResource();
|
Jedis jedis = jedisPool.getResource();
|
||||||
Transaction multi = jedis.multi();
|
jedis.set(keyPrefix + key, parse(value));
|
||||||
multi.set(keyPrefix + key, parse(value));
|
|
||||||
if(expire != null) {
|
if(expire != null) {
|
||||||
multi.expireAt(keyPrefix + key, expire.getTime());
|
jedis.pexpireAt(keyPrefix + key, expire.getTime());
|
||||||
log.debug("已设置Key {} 的过期时间(Expire: {})", key, expire.getTime());
|
log.debug("已设置Key {} 的过期时间(Expire: {})", key, expire.getTime());
|
||||||
}
|
}
|
||||||
multi.exec();
|
|
||||||
jedis.close();
|
jedis.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,4 +105,14 @@ public abstract class RedisPoolCacheStore<T> implements CacheStore<T> {
|
|||||||
public boolean supportedPersistence() {
|
public boolean supportedPersistence() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 替换原本的分隔符(.)为(:).<br/>
|
||||||
|
* 即将启用
|
||||||
|
* @param key 要处理的键名
|
||||||
|
* @return 处理后的键名
|
||||||
|
*/
|
||||||
|
public static String replaceKey(String key) {
|
||||||
|
return key.replaceAll("\\.", ":");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
30
src/main/java/net/lamgc/cgj/bot/cache/StringRedisCacheStore.java
vendored
Normal file
30
src/main/java/net/lamgc/cgj/bot/cache/StringRedisCacheStore.java
vendored
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package net.lamgc.cgj.bot.cache;
|
||||||
|
|
||||||
|
import redis.clients.jedis.JedisPool;
|
||||||
|
import redis.clients.jedis.JedisPoolConfig;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
public class StringRedisCacheStore extends RedisPoolCacheStore<String> {
|
||||||
|
public StringRedisCacheStore(URI redisServerUri, String prefix) {
|
||||||
|
super(redisServerUri, prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringRedisCacheStore(URI redisServerUri, JedisPoolConfig config, int timeout, String password, String prefix) {
|
||||||
|
super(redisServerUri, config, timeout, password, prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringRedisCacheStore(JedisPool pool, String keyPrefix) {
|
||||||
|
super(pool, keyPrefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String parse(String dataObj) {
|
||||||
|
return dataObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String analysis(String dataStr) {
|
||||||
|
return dataStr;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user