什么是缓存
缓存通俗点说就是临时存储数据的可高速访问的地方。
当从原始位置获取数据的代价太大或者时间太长的时候,就可以把获取到的数据存放在缓存中,这样下次访问的时候就提高了访问速度降低了访问成本。
缓存的基本知识点
- 缓存的对象
缓存的对象应该是花费了时间计算或者获取到的数据,并且这些数据在不久会被访问到。
在 Java 应用中,常见的缓存例子有如下几种
- Web Service 客户端调用结果的缓存
- 获取到的 DB 数据
- Servlet response 的缓存
- 复杂计算的结果
代码实例如 String 的 hashCode 计算结果
/** Cache the hash code for the string */
private int hash; // Default to 0
public int hashCode() {
//get from cache first
int h = hash;
//cannot found
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
//set to cache
hash = h;
}
return h;
}
- 缓存命中率
缓存命中指的是当前请求发生在缓存中,就是说数据可以从缓存中获得。
缓存命中率=缓存命中次数/总请求数[从缓存中读取+慢速设备读取]
缓存命中率是衡量缓存性能的一个重要指标。
- 缓存清除策略
当缓存失效或者缓存空间不足的时候,需要提供缓存算法来清除一些不再使用的缓存数据,这个时候就涉及到了缓存清除策略,一般称做缓存算法。
常见的缓存算法有:
- Least Recently Used (LRU)
- Most Recently Used (MRU)
- Least-Frequently Used(LFU)
- Low Inter-reference Recency Set (LIRS)
等,具体介绍请参考维基百科或者查阅对应算法资料。
- 缓存存活期 TTL(Time To Live)
存活期即从缓存中创建时间点开始直到它到期的一个时间段(不管在这个时间段内有没有访问都将过期) - 缓存空闲期 TTI(Time To Idle)
空闲期即一个数据多久没被访问将从缓存中移除的时间。
一般缓存使用方式
use cacheSpring cache abstraction
Spring cache 抽象层是 Spring 提供的一种能够极小冲击现有代码的缓存机制。它提供的是不依赖具体缓存框架的,使用 AOP 方式实现的缓存机制。
Spring 的缓存技术还具备相当的灵活性,不仅能够使用 SpEL(Spring Expression Language)来定义缓存的 key 和各种 condition,还提供开箱即用的缓存临时存储方案如 JDK 实现的缓存和 Guava cache,也支持和主流的专业缓存例如 EHCache 和 Redis 集成。
Spring 缓存技术基于 AOP 实现, 因此有两种实现模式 proxy 和 aspectj 可以选择以适应不同情况。
Spring cache 的使用方式
Spring cache 提供了一些注解来声明需要使用 Cache 的方法。
-
@Cacheable
声明使用 Cache,方式是 put if not found -
@CacheEvict
触发缓存清除操作 -
@CachePut
在方法执行的时候更新特定缓存,不影响方法执行结果 -
@Caching
如果一个方法有多个缓存操作可以使用 -
@CacheConfig
配置当前类中使用的缓存配置
每一个注解的使用说明请看 Spring 的文档。
使用 Spring Data Redis 实现 Cache
Spring data redis 是 Spring 提供的对 Redis 操作进行封装的框架,同时,他还提供了 Spring cache 的 Redis 实现,因此我们可以使用他来完成 Redis 缓存的集成。
Redis
Redis是一个开源、支持网络、基于内存、键值对存储数据库,可以用作数据库、缓存和消息中间件。将 Redis 作为缓存的时候应该注意:
- 设置最大可用的内存,使用
maxmemory
设置 - 设置 Key 的清除策略(也就是缓存策略),使用
maxmemory-policy
设置
如果不设置最大可用内存的话:32位操作系统,最大默认值为 3G,而64位则不限定。这样就会导致内存占用过多,并且可能会对缓存特定 Key 的检索速度有影响。
Redis 真正支持的缓存策略只有 LRU,但是我们可以在 redis.conf
中配置以下不同的参数,来实现不同效果的 Key 清除策略:
- noeviction:在客户端操作会导致更多内存占用的时候抛出错误。
- allkeys-lru: 优先清除最近最少使用的 key 来为新加数据让出空间。
- volatile-lru: 优先在设置了过期时间的 key 中清除最近最少使用的来为新加数据让出空间。
- allkeys-random: 随机清除 key 来为新加数据让出空间。
- volatile-random: 随机在设置了过期时间的 key 中清除一些
- volatile-ttl: 在设置了过期时间的 Key 中根据存活期长短来清除,优先清除存活期短的。
如果没有 Key 满足条件,volatile-lru、volatile-random 和 volatile-ttl 会和 noeviction 一样的表现。
配置 Redis 作为 Spring cache 实现
简单基于注解的配置如下:
@Configuration
@EnableCaching
public class CacheConfig extends CachingConfigurerSupport {
@Autowired
private RedisPropertiesVO properties;
@Bean
public JedisConnectionFactory jedisConnectionFactory() {
JedisConnectionFactory factory = new JedisConnectionFactory();
factory.afterPropertiesSet();
factory.setHostName(properties.getHost());
factory.setPort(properties.getPort());
factory.setUsePool(true);
factory.setDatabase(properties.getDatabase());
return factory;
}
@Bean
public RedisTemplate<Object, Object> redisTemplate() {
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(jedisConnectionFactory());
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
@Bean
public CacheManager cacheManager() {
return new RedisCacheManager(redisTemplate());
}
}
网友评论