缓存篇-本地缓存

Suffocat1ng

本地缓存有如下四个经典实现:HashMap, Guava Cache, Caffine, Encache

HashMap

利用LinkedHashMap实现LRU缓存,示例代码如下:

public class LRUCache extends LinkedHashMap {

    /**
     * 可重入读写锁,保证并发读写安全性
     */
    private ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
    private Lock readLock = readWriteLock.readLock();
    private Lock writeLock = readWriteLock.writeLock();

    /**
     * 缓存大小限制
     */
    private int maxSize;

    public LRUCache(int maxSize) {
        super(maxSize + 1, 1.0f, true);
        this.maxSize = maxSize;
    }

    @Override
    public Object get(Object key) {
        readLock.lock();
        try {
            return super.get(key);
        } finally {
            readLock.unlock();
        }
    }

    @Override
    public Object put(Object key, Object value) {
        writeLock.lock();
        try {
            return super.put(key, value);
        } finally {
            writeLock.unlock();
        }
    }

    // 只需要覆盖LinkedHashMap的removeEldestEntry方法,便可实现LRU淘汰策略
    @Override
    protected boolean removeEldestEntry(Map.Entry eldest) {
        return this.size() > maxSize;
    }
}

Guava Cache

特点

  • 支持最大容量限制。
  • 支持两种过期删除策略(插入时间和访问时间)。
  • 基于LRU淘汰算法。
  • 支持简单的统计功能。

示例代码如下:

public class GuavaCacheTest {
    public static void main(String[] args) throws Exception {
        //创建guava cache
        Cache<String, String> loadingCache = CacheBuilder.newBuilder()
                //cache的初始容量
                .initialCapacity(5)
                //cache最大缓存数
                .maximumSize(10)
                //设置写缓存后n秒钟过期
                .expireAfterWrite(17, TimeUnit.SECONDS)
                //设置读写缓存后n秒钟过期,实际很少用到,类似于expireAfterWrite
                //.expireAfterAccess(17, TimeUnit.SECONDS)
                .build();
        String key = "key";
        // 往缓存写数据
        loadingCache.put(key, "v");

        // 获取value的值,如果key不存在,调用collable方法获取value值加载到key中再返回
        String value = loadingCache.get(key, new Callable<String>() {
            @Override
            public String call() throws Exception {
                return getValueFromDB(key);
            }
        });

        // 删除key
        loadingCache.invalidate(key);
    }

    private static String getValueFromDB(String key) {
        return "v";
    }
}

Caffeine

特点

  • 是Guava Cache的增强版,性能更优。
  • 基于结合LRU, LFU的淘汰算法:W-TinyLFU。

示例代码如下:

public class CaffeineCacheTest {
    public static void main(String[] args) throws Exception {
        //创建guava cache
        Cache<String, String> loadingCache = Caffeine.newBuilder()
                //cache的初始容量
                .initialCapacity(5)
                //cache最大缓存数
                .maximumSize(10)
                //设置写缓存后n秒钟过期
                .expireAfterWrite(17, TimeUnit.SECONDS)
                //设置读写缓存后n秒钟过期,实际很少用到,类似于expireAfterWrite
                //.expireAfterAccess(17, TimeUnit.SECONDS)
                .build();
        String key = "key";
        // 往缓存写数据
        loadingCache.put(key, "v");

        // 获取value的值,如果key不存在,获取value后再返回
        String value = loadingCache.get(key, CaffeineCacheTest::getValueFromDB);

        // 删除key
        loadingCache.invalidate(key);
    }

    private static String getValueFromDB(String key) {
        return "v";
    }
}

Encache

特点:

  • 纯java的进程内缓存框架。
  • 是Hibernate中默认的Cache Provider。
  • 支持FIFO, LRU, LFU淘汰算法。
  • 支持堆内存储、堆外存储和磁盘存储(持久化)。
  • 支持多种集群方案,解决数据共享问题。

示例代码如下:

public class EncacheTest {

    public static void main(String[] args) throws Exception {
        // 声明一个cacheBuilder
        CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder()
                .withCache("encacheInstance", CacheConfigurationBuilder
                        //声明一个容量为20的堆内缓存
                        .newCacheConfigurationBuilder(String.class,String.class, ResourcePoolsBuilder.heap(20)))
                .build(true);
        // 获取Cache实例
        Cache<String,String> myCache =  cacheManager.getCache("encacheInstance", String.class, String.class);
        // 写缓存
        myCache.put("key","v");
        // 读缓存
        String value = myCache.get("key");
        // 移除换粗
        cacheManager.removeCache("myCache");
        cacheManager.close();
    }
}

四种本地缓存性能比较

image.png

结论:本地缓存优先考虑:Caffine。

参考文献

https://juejin.cn/post/684490...

阅读 140
1 声望
0 粉丝
0 条评论
你知道吗?

1 声望
0 粉丝
宣传栏