Skip to content

SivanCache的固定缓存大小实现

Sivan_Xin edited this page Dec 11, 2023 · 4 revisions

代码实现 定义SivanCache接口,实现put方法 @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());
}

Clone this wiki locally