本地热点缓存解决分布式项目在redis里面添加缓存(分布式session缓存)时会产生频繁的网络io开销。
将缓存存储在springboot项目所在的服务器上。(会产生缓存命中率问题)
对于缓存与数据库数据不一致的脏数据情况的解决方法:
1.设置缓存的过期时间
2.在执行缓存相关表格的增,删,改操作时要同时执行缓存删除的操作。
使用到的技术
实现步骤:
一、引包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<!-- 对象转json工具-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
<!--谷歌瓜娃 https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
二、定义缓存服务接口
package com.etc.service;
/**
* @Author kalista
* @Description 缓存接口
* @Date 2021/4/21 19:58
**/
public interface ICacheService {
//存
void setCommonCache(String key,Object value);
// 取
Object getCommonCache(String key);
}
三、定义缓存服务实现类
设置缓存容器初始化信息(最大、最小值、过期时间)
package com.etc.service.impl;
import com.etc.service.ICacheService;
import com.google.common.cache.CacheBuilder;
import org.springframework.stereotype.Service;
import com.google.common.cache.Cache;
import javax.annotation.PostConstruct;
import java.util.concurrent.TimeUnit;
/**
* @Author kalista
* @Description
* @Date 2021/4/21 20:00
**/
@Service
public class cacheService implements ICacheService {
private Cache<String,Object> commonCache = null;
//postConstruct 用来修饰一个静态的void方法,在服务器加载servlet时候运行,并且只会服务器执行一次
// 构造方法--> Autowired依赖注入---> postConsyructs注释方法
@PostConstruct
public void init(){
commonCache = CacheBuilder.newBuilder()
//设置缓存容器的初始容量 为 10
.initialCapacity(10)
//设置缓存中最大可以存储100个key 超过100 之后 会按照LRU算法策略移除缓存 (LRU 最近最少使用)
.maximumSize(100)
//设置写缓存的多少秒过期
.expireAfterWrite(60, TimeUnit.SECONDS).build();
}
/**
* 存缓存
* @param key
* @param value
*/
@Override
public void setCommonCache(String key, Object value) {
commonCache.put(key,value);
}
/**
* 取缓存
* @param key
* @return
*/
@Override
public Object getCommonCache(String key) {
return commonCache.getIfPresent(key);
}
}
四、在service或controller中应用缓存
public String index(ModelMap modelMap, HttpSession session) {
// 先查缓存 redis 有没有
List<Type> types1 = null;
types1 = (List<Type>) iCacheService.getCommonCache("types");
//本地缓存为空
if (types1==null || types1.isEmpty()){
String types = redisTemplate.opsForValue().get("types");
// 如果为空从数据库查询
if (StringUtils.isEmpty(types)){
//如果没有缓存查数据库
types1 = typeService.list();
if (types1 != null && !types1.isEmpty()){
// list 对象转 json
String s = JSON.toJSONString(types1);
redisTemplate.opsForValue().set("types",s);
iCacheService.setCommonCache("types",types1);
session.setAttribute("types",types1);
}
}else {
// 有缓存
types1 = (List<Type>) JSON.parse(types);
iCacheService.setCommonCache("types",types1);
//查询水果类型
session.setAttribute("types",types1);
}
}
}