使用场景
由于公司Redis负载过大,且主从集群的设置性能较低,调用次数峰值能到达每秒5W多次,命中率仅30%,于是需要在使用的服务器上面,对特定的Redis数据添加Guava作为服务器二级缓存。
guava cache一般不用于通用的二级缓存,而是作为特定某些key值的二级缓存。
引入依赖
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
代码
package com.ofpay.ofrc.order.service.sla;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
/**
* @author yjj
* @date 2023/3/3
*/
@Slf4j
@Component
public class CacheService {
@Value("${cache.initialCapacity:30}")
private int initialCapacity;
@Value(("${cache.maxSize:10000}"))
private int maxSize;
@Value("${cache.expireMinutes:10000}")
private int expireMinutes;
private LoadingCache<String, String> cache;
@Autowired
private RedisTemplate<String, String> redisTemplate;
/**
* guava缓存容器初始化
*
* @return 缓存容器
*/
@PostConstruct
private void loadCache() {
cache = CacheBuilder.newBuilder()
.concurrencyLevel(Runtime.getRuntime().availableProcessors())
// 设置初始容量
.initialCapacity(initialCapacity)
// 设置缓存池大小
.maximumSize(maxSize)
// 设置失效时间
.refreshAfterWrite(expireMinutes, TimeUnit.MINUTES)
.build(new CacheLoader<String, String>() {
public String load(String key) {
log.info("从Redis中加载数据到guava中,key为{}", key);
return redisTemplate.opsForValue().get(key);
}
});
}
/**
* 根据key获取缓存
*
* @param key 键
* @return
*/
public String get(String key) {
if (StringUtils.isBlank(key)) {
log.info("获取缓存的key值为空");
return null;
}
try {
log.info("从guava缓存中获取值!key:{}", key);
return cache.get(key);
} catch (ExecutionException e) {
log.error("获取缓存值出错!key为{}", key);
return null;
}
}
/**
* 设置缓存
*
* @Param key 键
* @Param value 值
*/
public void put(String key, String value) {
if (StringUtils.isBlank(key)) {
log.error("设置的key值不可为空!");
return;
}
cache.put(key, value);
redisTemplate.opsForValue().set(key, value);
}
}