-
Notifications
You must be signed in to change notification settings - Fork 20
SivanCache的固定缓存大小实现
Sivan_Xin edited this page Dec 11, 2023
·
4 revisions
@Override
@SivanCacheInterceptor(aof = true, evict = true)
public V put(K key, V value) {
//1.1 尝试驱除
SivanCacheEvictContext<K,V> context = new SivanCacheEvictContext<>();
context.key(key).size(sizeLimit).cache(this);
ISivanCacheEntry<K,V> evictEntry = evict.evict(context);
// 添加拦截器调用
if(ObjectUtil.isNotNull(evictEntry)) {
// 执行淘汰监听器
ISivanCacheRemoveListenerContext<K,V> removeListenerContext = SivanCacheRemoveListenerContext.<K,V>newInstance().key(evictEntry.key())
.value(evictEntry.value())
.type(SivanCacheRemoveType.EVICT.code());
for(ISivanCacheRemoveListener<K,V> listener : context.cache().removeListeners()) {
listener.listen(removeListenerContext);
}
}
//2. 判断驱除后的信息
if(isSizeLimit()) {
throw new SivanCacheRuntimeException("当前队列已满,数据添加失败!");
}
//3. 执行添加
return map.put(key, value);
}
先实现一个简单的缓存淘汰策略
package com.xin.cache.support.evict;
import com.xin.cache.api.ISivanCache;
import com.xin.cache.api.ISivanCacheEvictContext;
import com.xin.cache.model.SivanCacheEntry;
import java.util.LinkedList;
import java.util.Queue;
/**
* 丢弃策略-先进先出
* @author sivan
*
*/
public class SivanCacheEvictFifo<K,V> extends AbstractSivanCacheEvict<K,V> {
/**
* queue 信息
*
*/
private final Queue<K> queue = new LinkedList<>();
@Override
public SivanCacheEntry<K,V> doEvict(ISivanCacheEvictContext<K, V> context) {
SivanCacheEntry<K,V> result = null;
final ISivanCache<K,V> cache = context.cache();
// 超过限制,执行移除
if(cache.size() >= context.size()) {
K evictKey = queue.remove();
// 移除最开始的元素
V evictValue = cache.remove(evictKey);
result = new SivanCacheEntry<>(evictKey, evictValue);
}
// 将新加的元素放入队尾
final K key = context.key();
queue.add(key);
return result;
}
}
package com.xin.cache.bs;
import com.github.houbb.heaven.util.common.ArgUtil;
import com.xin.cache.api.*;
import com.xin.cache.core.SivanCache;
import com.xin.cache.support.evict.SivanCacheEvicts;
import com.xin.cache.support.listener.remove.SivanCacheRemoveListeners;
import com.xin.cache.support.listener.slow.SivanCacheSlowListeners;
import com.xin.cache.support.load.SivanCacheLoads;
import com.xin.cache.support.persist.SivanCachePersists;
import com.xin.cache.support.proxy.SivanCacheProxy;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 缓存引导类
* @author sivan
*
*/
public final class SivanCacheBs<K,V> {
private SivanCacheBs(){}
/**
* 创建对象实例
* @param <K> key
* @param <V> value
* @return this
*
*/
public static <K,V> SivanCacheBs<K,V> newInstance() {
return new SivanCacheBs<>();
}
/**
* map 实现
*
*/
private Map<K,V> map = new HashMap<>();
/**
* 大小限制
*
*/
private int size = Integer.MAX_VALUE;
/**
* 驱除策略
*
*/
private ISivanCacheEvict<K,V> evict = SivanCacheEvicts.fifo();
/**
* 删除监听类
*
*/
private final List<ISivanCacheRemoveListener<K,V>> removeListeners = SivanCacheRemoveListeners.defaults();
/**
* 慢操作监听类
*
*/
private final List<ISivanCacheSlowListener> slowListeners = SivanCacheSlowListeners.none();
/**
* 加载策略
*
*/
private ISivanCacheLoad<K,V> load = SivanCacheLoads.none();
/**
* 持久化实现策略
*
*/
private ISivanCachePersist<K,V> persist = SivanCachePersists.none();
/**
* map 实现
* @param map map
* @return this
*
*/
public SivanCacheBs<K, V> map(Map<K, V> map) {
ArgUtil.notNull(map, "map");
this.map = map;
return this;
}
/**
* 设置 size 信息
* @param size size
* @return this
*
*/
public SivanCacheBs<K, V> size(int size) {
ArgUtil.notNegative(size, "size");
this.size = size;
return this;
}
/**
* 设置驱除策略
* @param evict 驱除策略
* @return this
*
*/
public SivanCacheBs<K, V> evict(ISivanCacheEvict<K, V> evict) {
ArgUtil.notNull(evict, "evict");
this.evict = evict;
return this;
}
/**
* 设置加载
* @param load 加载
* @return this
*
*/
public SivanCacheBs<K, V> load(ISivanCacheLoad<K, V> load) {
ArgUtil.notNull(load, "load");
this.load = load;
return this;
}
/**
* 添加删除监听器
* @param removeListener 监听器
* @return this
*
*/
public SivanCacheBs<K, V> addRemoveListener(ISivanCacheRemoveListener<K,V> removeListener) {
ArgUtil.notNull(removeListener, "removeListener");
this.removeListeners.add(removeListener);
return this;
}
/**
* 添加慢日志监听器
* @param slowListener 监听器
* @return this
*
*/
public SivanCacheBs<K, V> addSlowListener(ISivanCacheSlowListener slowListener) {
ArgUtil.notNull(slowListener, "slowListener");
this.slowListeners.add(slowListener);
return this;
}
/**
* 设置持久化策略
* @param persist 持久化
* @return this
*
*/
public SivanCacheBs<K, V> persist(ISivanCachePersist<K, V> persist) {
this.persist = persist;
return this;
}
/**
* 构建缓存信息
* @return 缓存信息
*
*/
public ISivanCache<K,V> build() {
SivanCache<K,V> cache = new SivanCache<>();
cache.map(map);
cache.evict(evict);
cache.sizeLimit(size);
cache.removeListeners(removeListeners);
cache.load(load);
cache.persist(persist);
cache.slowListeners(slowListeners);
// 初始化
cache.init();
return SivanCacheProxy.getProxy(cache);
}
}
/**
* 大小指定测试
*
*/
@Test
public void helloTest() {
ISivanCache<String, String> cache = SivanCacheBs.<String,String>newInstance()
.size(2)
.build();
cache.put("1", "1");
cache.put("2", "2");
cache.put("3", "3");
cache.put("4", "4");
Assert.assertEquals(2, cache.size());
System.out.println(cache.keySet());
}