一、缓存
1,缓存的使用
为了系统性能的提升,我们一般都会将部分数据放入缓存中,加速访问。而 db 承担数据落 盘工作。
哪些数据适合放入缓存?
(1)即时性、数据一致性要求不高的
(2)访问量大且更新频率不高的数据(读多,写少)
举例:电商类应用,商品分类,商品列表等适合缓存并加一个失效时间(根据数据更新频率来定),后台如果发布一个商品,买家需要 5 分钟才能看到新的商品一般还是可以接受的。
本地缓存与分布式缓存
本地缓存:和微服务同一个进程。缺点:分布式时本地缓存不能共享
分布式缓存:缓存中间件,例如:redis
2,整合redis作为缓存
1安装redis
官网下载
2pom.xml中引入redis依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
版本统一交给父项目管理
3在application.yml添加redis配置
位于spring下
4使用StringRedisTemplate操作redis
@Resource
StringRedisTemplate stringRedisTemplate;
@Test
public void testRedisTeplate(){
//hello world
ValueOperations<String, String> stringStringValueOperations = stringRedisTemplate.opsForValue();
//保存
stringStringValueOperations.set("hello","world_"+ UUID.randomUUID().toString());
//查询
String hello = stringStringValueOperations.get("hello");
System.out.println(hello);
}
测试结果如下
5切换使用jedis解决OutOfDirectMemoryError 堆外内存溢出
//1)springboot2.0以后默认使用lettuce作为操作redis的客户端。它使用netty进行网络通信
//2)lettuce的bug导致堆外内存溢出 -Xmx300m; netty如果没有指定堆外内存 默认使用-Xmx300m;
// 可以通过-Dio.netty.maxDirectMemory进行设置
//解决方案:不能使用-Dio.netty.maxDirectMemory只去调大堆外内存
//1)升级lettuce客户端 2)切换使用jedis
//RedisTemplate
//lettuce jedis操作redis的底层客户端 spring再次封装成RedisTemplate;
修改pom.xml 切换使用jedis
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
3,改造三级分类业务
修改product模块中CategoryServiceImpl方法
@Autowired
StringRedisTemplate redisTemplate;
//TODO 产生堆外内存溢出:OutOfDirectMemoryError
//(1)springboot2.0以后默认使用lettuce作为操作redis客户端。它使用netty进行网络通信
//(2)lettuce的bug导致netty堆外内存溢出 -Xmx300m;netty如果没有指定堆外内存,默认使用-Xmx300m
// 可以通过-Dio.netty.maxDirectMemory进行设置
// 解决方案:不能使用-Dio.netty.maxDirectMemory只去调大堆外内存。
//(1)升级lettuce客户端
//(2)切换使用jedis
@Override
public Map<String, List<Catelog2Vo>> getCatalogJson() {
//给缓存中放json字符串,拿出的json字符串,还要逆转为能用的对象类型:【序列化与反序列化】
//1、加入缓存逻辑,缓存中存的数据是json字符串
//JSO跨语言、跨平台兼容
String catalogJson = redisTemplate.opsForValue().get("catalogJson");
if(StringUtils.isEmpty(catalogJson)){
//2、缓存中没有,查询数据库
Map<String, List<Catelog2Vo>> catalogJsonFromDb = getCatalogJsonFromDb();
//3、查到的数据再放入缓存,将对象转为json放到缓存中
String s = JSON.toJSONString(catalogJsonFromDb);
redisTemplate.opsForValue().set("catalogJson", s);
return catalogJsonFromDb;
}
//转为我们指定的对象
Map<String, List