缓存设计
缓存设计考虑点:
- 存储的数据结构
- 缓存容量大小
- 缓存有效期
- 容量不够时的清理策略
- 缓存设计相关指标(命中率、命中次数、miss率等)
缓存设计过程:
- 全局的hash表,Key-Value键值对
- 提供get/put等方法来操作缓存
- 规定最大容量
- 记录缓存访问时间,决定缓存是否失效
- 容量不够时LRU/FIFO/LFU来做清理
- 每次get方法做结果统计
guava cache
类似于ConcurrentMap,支持高并发,是线程安全的,ConcurrentMap添加元素,不显式移除的话一直存在Map中,但是Cache会有失效策略,以及支持高并发.
- new Builder:cache构造器,builder模式
- maximumSize:缓存最大容量
- expireAfterAccess:缓存有效期
- refreshAfterWrite:自动刷新缓存时间间隔
- recordStats:记录缓存使用情况
- CacheLoader:定义缓存刷新的方法
例子:
public static void test9() throws ExecutionException {
LoadingCache<String,TestPojo> loadingCache = CacheBuilder.newBuilder()
.maximumSize(1000)
.expireAfterAccess(30, TimeUnit.MINUTES)
.refreshAfterWrite(10,TimeUnit.MINUTES)
.removalListener(new RemovalListener<String, TestPojo>() {
public void onRemoval(RemovalNotification<String, TestPojo> removalNotification)
{
//TODO
}
})
.recordStats()
.build(new CacheLoader<String, TestPojo>() {
@Override
public TestPojo load(String s) throws Exception {
return fetchFromDB(s);
}
});
loadingCache.get("aaa"); //get时,如果缓存中没有。则到数据库中查找
loadingCache.put("bbb",new TestPojo());
}
private static TestPojo fetchFromDB(String s) {
return new TestPojo();
}
优点:
- 使用简单
- 线程安全,内部实现类似于ConcurrentHashMap
- 可以自动加载、定时更新缓存
- 容量不够时LRU清理
- 记录访问时间用于计算是否有效
- key/value支持多种引用类型
- 溶剂缓存访问数据
- 缓存被移除或失效时可以被“监听”
- 考虑:数据量、数据变化
局限:
- 单个应用运行时的本地缓存,数据并没有持久化存放到某个文件或外部服务器;
- 单机,受机器内存限制,重启应用缓存数据会丢失。应用分布式部署会出现缓存数据不一致。
redis
原理:
- KV Nosql
- 缓存在内存
- 支持多种数据结构:string,hash,list,set,zset
- 可持久化:AOF(日志) vs RDB(快照)
- 高性能、高可靠
- 支持主从复制
- 支持事务
redis安装
安装参考
启动:
服务器端:src/redis-server
客户端:src/redis-cli
常用命令:
set ccc ccc
get ccc
lpush ccclist list1
lpush ccclist list2
lrange ccclist 0 -1