首先,我们要在application.yml配置文件中简单的配置一下redis一些相关配置信息:
redis:
host: 192.168.179.5 #Redis服务器的主机名或IP地址,用于建立与Redis服务器的连接
password: 123 #密码 port: 6379
port: 6379 #默认端口号是6379
database: 7 #数据库7号
然后我们模拟前端发送请求写一个控制器类:
1.先写一个响应结果的封装类
package com.zzx.plus.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result<T> {
private T data;
private String erromsg;
private Boolean succesed;
public static <T>Result<T> ok(T data){
return new Result<T>(data,null,true);
}
}
2.再编写一个控制器类处理前端发送过来的请求并编写核心缓存逻辑,当然实际开发中缓存逻辑不建议写在控制器方法中
package com.zzx.plus.controller;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.zzx.plus.dto.Result;
import com.zzx.plus.mapper.UserMapper;
import com.zzx.plus.pojos.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.security.Key;
@RestController
@RequestMapping("/user")
public class userController {
@Autowired
private UserMapper userMapper;
@Autowired
private StringRedisTemplate stringRedisTemplate;
@GetMapping("/list")
public Result<User> list(Long id){
//根据id生成动态key值
String user_key = "user:"+id;
//查询缓存
String user1 = stringRedisTemplate.opsForValue().get(user_key);
//如果命中缓存
if (StrUtil.isNotBlank(user1)) {
//解析成user对象
User user = JSONUtil.toBean(user1, User.class);
return Result.ok(user);
}
//如果命中为空在返回错误信息
if (user1!=null) {
return Result.erro("错误,请输入正确的地址");
}
//如果未命中缓存
//查询数据库
User user = userMapper.selectByid(id);
//如果查询不到缓存空值
if (user==null) {
stringRedisTemplate.opsForValue().set(user_key,"");
}
//构建缓存
stringRedisTemplate.opsForValue().set(user_key,JSONUtil.toJsonStr(user));
//返回结果集
return Result.ok(user);
}
}
3.我们再用postman来模仿前端发送请求来走后端控制器方法的缓存逻辑:
这里我们可以看到redis中有了缓存,然后也看到了响应结果,说明逻辑没有问题。我们可以重复上述操作,用postman反复发送请求,结果在最后的日志信息中,只看到了一次数据库查询操作,说明只有第一次是查询数据库的,因为第一次没有缓存,而以后的查询操作都是走的Redis的缓存
4.
缓存和数据库双写一致性问题
一致性的问题很常见,因为加入了缓存之后,请求是先从 redis 中查询,如果 redis 中
存在数据就不会走数据库了,如果在这期间对数据库进行更新或者删除操作,那就会导致缓存中数据与数据库中数据不一致的情况,为了解决这种情况,我们可以这样做
@PostMapping("/update")
public Result<String> update(@RequestBody User user){
//获得动态key
String key = "user:"+user.getId();
//修改数据库
userMapper.updateById(user);
//删除缓存
stringRedisTemplate.delete(key);
return Result.ok("修改成功!");
}
在数据库更新操作后,删除缓存,这样下一次查询时就会构建新的缓存,这样就保证了数据的一致性。但是需要注意的是,要先修改数据库再删除缓存,这样做的目的是,因为删除缓存的是对redis的操作要比对数据库的操作要快得多,如果在高并发的情况下,先删除缓存,马上进行查询操作这样查询的还是旧数据,因为数据库操作很慢来不及修改,所以修改数据库的操作要在删除缓存前执行。