如果只使用redis来做缓存我们会有大量的请求到redis,但是每次请求的数据都是一样的,假如这一部分数据就放在应用服务器本地,那么就省去了请求redis的网络开销,请求速度就会快很多。但是使用redis横向扩展很方便。
如果只使用Caffeine来做本地缓存,我们的应用服务器的内存是有限,并且单独为了缓存去扩展应用服务器是非常不划算。所以,只使用本地缓存也是有很大局限性的。
我们在项目中使用了两级缓存
本地缓存的时间为60秒,过期后则从redis中取数据,
如果redis中不存在,则从数据库获取数据,
application.properties
#redis1
spring.redis1.host=127.0.0.1
spring.redis1.port=6379
spring.redis1.password=lhddemo
spring.redis1.database=0
spring.redis1.lettuce.pool.max-active=32
spring.redis1.lettuce.pool.max-wait=300
spring.redis1.lettuce.pool.max-idle=16
spring.redis1.lettuce.pool.min-idle=8
spring.redis1.enabled=1
#profile
spring.profiles.active=cacheenable
CREATE TABLE `goods` (
`goodsId` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
`goodsName` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT 'name',
`subject` varchar(200) NOT NULL DEFAULT '' COMMENT '标题',
`price` decimal(15,2) NOT NULL DEFAULT '0.00' COMMENT '价格',
`stock` int(11) NOT NULL DEFAULT '0' COMMENT 'stock',
PRIMARY KEY (`goodsId`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='商品表'
CacheConfig.java
"cacheenable") //prod这个profile时缓存才生效 (
//开启缓存
public class CacheConfig {
public static final int DEFAULT_MAXSIZE = 10000;
public static final int DEFAULT_TTL = 600;
private SimpleCacheManager cacheManager = new SimpleCacheManager();
//定义cache名称、超时时长(秒)、最大容量
public enum CacheEnum{
goods(60,1000), //有效期60秒 , 最大容量1000
homePage(7200,1000), //有效期2个小时 , 最大容量1000
;
CacheEnum(int ttl, int maxSize) {
this.ttl = ttl;
this.maxSize = maxSize;
}
private int maxSize=DEFAULT_MAXSIZE; //最大數量
private int ttl=DEFAULT_TTL; //过期时间(秒)
public int getMaxSize() {
return maxSize;
}
public int getTtl() {
return ttl;
}
}
//创建基于Caffeine的Cache Manager
public CacheManager caffeineCacheManager() {
ArrayList<CaffeineCache> caches = new ArrayList<CaffeineCache>();
for(CacheEnum c : CacheEnum.values()){
caches.add(new CaffeineCache(c.name(),
Caffeine.newBuilder().recordStats()
.expireAfterWrite(c.getTtl(), TimeUnit.SECONDS)
.maximumSize(c.getMaxSize()).build())
);
}
cacheManager.setCaches(caches);
return cacheManager;
}
public CacheManager getCacheManager() {
return cacheManager;
}
}
RedisConfig.java
public class RedisConfig {
public LettuceConnectionFactory redis1LettuceConnectionFactory(RedisStandaloneConfiguration redis1RedisConfig,
GenericObjectPoolConfig redis1PoolConfig) {
LettuceClientConfiguration clientConfig =
LettucePoolingClientConfiguration.builder().commandTimeout(Duration.ofMillis(100))
.poolConfig(redis1PoolConfig).build();
return new LettuceConnectionFactory(redis1RedisConfig, clientConfig);
}
public RedisTemplate<String, String> redis1Template(
LettuceConnectionFactory redis1LettuceConnectionFactory) {
RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
//使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
//使用StringRedisSerializer来序列化和反序列化redis的key值
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
//开启事务
redisTemplate.setEnableTransactionSupport(true);
redisTemplate.setConnectionFactory(redis1LettuceConnectionFactory);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
public static class Redis1Config {
private String host;
private Integer port;
private String password;
private Integer database;
private Integer maxActive;
private Integer maxIdle;
private Long maxWait;
private Integer minIdle;
public GenericObjectPoolConfig redis1PoolConfig() {
GenericObjectPoolConfig config = new GenericObjectPoolConfig();
config.setMaxTotal(maxActive);
config.setMaxIdle(maxIdle);
config.setMinIdle(minIdle);
config.setMaxWaitMillis(maxWait);
return config;
}
public RedisStandaloneConfiguration redis1RedisConfig() {
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
config.setHostName(host);
config.setPassword(RedisPassword.of(password));
config.setPort(port);
config.setDatabase(database);
return config;
}
}
}
HomeController.java
//商品详情 参数:商品id
public Goods goodsInfo( Long goodsId) {
Goods goods = goodsService.getOneGoodsById(goodsId);
return goods;
}
GoodsServiceImpl.java
public Goods getOneGoodsById(Long goodsId) {
Goods goodsOne;
if (redis1enabled == 1) {
System.out.println("get data from redis");
Object goodsr = redis1Template.opsForValue().get("goods_"+String.valueOf(goodsId));
if (goodsr == null) {
System.out.println("get data from mysql");
goodsOne = goodsMapper.selectOneGoods(goodsId);
if (goodsOne == null) {
redis1Template.opsForValue().set("goods_"+String.valueOf(goodsId),"-1",600, TimeUnit.SECONDS);
} else {
redis1Template.opsForValue().set("goods_"+String.valueOf(goodsId),goodsOne,600, TimeUnit.SECONDS);
}
} else {
if (goodsr.equals("-1")) {
goodsOne = null;
} else {
goodsOne = (Goods)goodsr;
}
}
} else {
goodsOne = goodsMapper.selectOneGoods(goodsId);
}
return goodsOne;
}
http://127.0.0.1:8080/home/goodsget?goodsid=3
get data from redis
get data from mysql
costtime aop 方法doafterreturning:毫秒数:395
costtime aop 方法doafterreturning:毫秒数:0
get data from redis
costtime aop 方法doafterreturning:毫秒数:8
福 利
CSDN旗下公众号全新搜索技能上线啦!
只要在公众号内回复消息
就能自动回复想搜索的内容啦!
现在体验有惊喜,每日参与搜索打卡,
连续打卡满3天、7天、14天
均有CSDN精美礼品相送 百分百有礼!快戳
更多精彩推荐
☞开源数据库再创里程碑,PingCAP 获 2.7 亿美元融资
☞全球数百万台 Mac 疑似因 Big Sur 更新险酿计算灾难,苹果官方回应来了! ☞ JavaScript 稳居第一、C# 连续下跌,调查 17000 名程序员后有了这些新发现! ☞ 中国第一代程序员潘爱民的 30 年程序人生
☞ 漫画:什么是 “千年虫” 问题? ☞ 万万没想到 Java 中最重要的关键字竟然是这个!
![]()
点分享 ![]()
点点赞 ![]()
点在看