缓存

缓存设计

缓存设计考虑点:

  1. 存储的数据结构
  2. 缓存容量大小
  3. 缓存有效期
  4. 容量不够时的清理策略
  5. 缓存设计相关指标(命中率、命中次数、miss率等)

缓存设计过程:

  1. 全局的hash表,Key-Value键值对
  2. 提供get/put等方法来操作缓存
  3. 规定最大容量
  4. 记录缓存访问时间,决定缓存是否失效
  5. 容量不够时LRU/FIFO/LFU来做清理
  6. 每次get方法做结果统计

guava cache

类似于ConcurrentMap,支持高并发,是线程安全的,ConcurrentMap添加元素,不显式移除的话一直存在Map中,但是Cache会有失效策略,以及支持高并发.

  • new Builder:cache构造器,builder模式
  • maximumSize:缓存最大容量
  • expireAfterAccess:缓存有效期
  • refreshAfterWrite:自动刷新缓存时间间隔
  • recordStats:记录缓存使用情况
  • CacheLoader:定义缓存刷新的方法
    例子:
guava-chache示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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
常用命令参考