言
对一个java后台开发者而言,提到缓存,第一反应就是redis和memcache。利用这类缓存足以解决大多数的性能问题了,并且java针对这两者也都有非常成熟的api可供使用。但是我们也要知道,这两种都属于remote cache(分布式缓存),应用的进程和缓存的进程通常分布在不同的服务器上,不同进程之间通过RPC或HTTP的方式通信。这种缓存的优点是缓存和应用服务解耦,支持大数据量的存储,缺点是数据要经过网络传输,性能上会有一定损耗。
与分布式缓存对应的是本地缓存,缓存的进程和应用进程是同一个,数据的读写都在一个进程内完成,这种方式的优点是没有网络开销,访问速度很快。缺点是受JVM内存的限制,不适合存放大数据。
本篇文章我们主要主要讨论Java本地缓存的的一些常用方案。
本地缓存常用技术
本地缓存和应用同属于一个进程,使用不当会影响服务稳定性,所以通常需要考虑更多的因素,例如容量限制、过期策略、淘汰策略、自动刷新等。常用的本地缓存方案有:
- 根据HashMap自实现本地缓存
- Guava Cache
- Caffeine
- Encache
下面分别进行介绍:
1. 根据HashMap自定义实现本地缓存
缓存的本质就是存储在内存中的KV数据结构,对应的就是jdk中的HashMap,但是要实现缓存,还需要考虑并发安全性、容量限制等策略,下面简单介绍一种利用LinkedHashMap实现缓存的方式:
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();
}
}
@Ove