# 缓存和分布式锁
# 一、缓存
## 1. 什么是缓存
缓存的作用是减低对数据源的访问频率。从而提高我们系统的性能。
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1647243560000/f7b9a0b66af14121aadeb50bffd8e36c.png)
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1647243560000/cb0dbab831954c11bd7e3873914f7150.png)
缓存的流程图
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1647243560000/cba94b3b543247feb6d8099a6ccc5d2f.png)
## 2.缓存的分类
### 2.1 本地缓存
其实就是把缓存数据存储在内存中(Map `<String,Object>`).在单体架构中肯定没有问题。
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1647243560000/8b6494222e834cc895c5934b15836c95.png)
单体架构下的缓存处理
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1647243560000/fc2ef64e7b734fa6b4702420be0d5a36.png)
### 2.2 分布式缓存
在分布式环境下,我们原来的本地缓存就不是太使用了,原因是:
* 缓存数据冗余
* 缓存效率不高
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1647243560000/7465ee4dee6b4d0c9f4b61ba93dbfa87.png)
分布式缓存的结构图
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1647243560000/b252ba1016044eca891ab5b3bdf9d1e0.png)
## 3.整合Redis
要整合Redis那么我们在SpringBoot项目中首页来添加对应的依赖
```xml
org.springframework.boot
spring-boot-starter-data-redis
```
然后我们需要添加对应的配置信息
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1647243560000/753f65df9029411a8145b2477d1e58d3.png)
测试操作Redis的数据
```java
@Autowired
StringRedisTemplate stringRedisTemplate;
@Test
public void testStringRedisTemplate(){
// 获取操作String类型的Options对象
ValueOperations ops = stringRedisTemplate.opsForValue();
// 插入数据
ops.set("name","bobo"+ UUID.randomUUID());
// 获取存储的信息
System.out.println("刚刚保存的值:"+ops.get("name"));
}
```
查看可以通过Redis的客户端连接查看
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1647243560000/1b678ea26d684404a93217b8bb781164.png)
也可以通过工具查看
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1647243560000/33e044f827f0470bb9f3a27308f77118.png)
## 4.改造三级分类
在首页查询二级和三级分类数据的时候我们可以通过Redis来缓存存储对应的数据,来提升检索的效率。
```java
@Override
public Map> getCatelog2JSON() {
// 从Redis中获取分类的信息
String catalogJSON = stringRedisTemplate.opsForValue().get("catalogJSON");
if(StringUtils.isEmpty(catalogJSON)){
// 缓存中没有数据,需要从数据库中查询
Map> catelog2JSONForDb = getCatelog2JSONForDb();
// 从数据库中查询到的数据,我们需要给缓存中也存储一份
String json = JSON.toJSONString(catelog2JSONForDb);
stringRedisTemplate.opsForValue().set("catalogJSON",json);
return catelog2JSONForDb;
}
// 表示缓存命中了数据,那么从缓存中获取信息,然后返回
Map> stringListMap = JSON.parseObject(catalogJSON, new TypeReference