前言:在开发后台的时候,通过Redis对分页查询的数据进行了缓存,但是数据在做新增、删除、更新的时候,为了保持Redis中缓存的数据与数据库中的数据保持一致性,需要对缓存也进行更新处理

这里我用的更新方法也是非常简单暴力,就在查询的时候,会对Redis进行一次查询,根据分页的页码和相对应的表。如果查到的缓存为空,那么就会去数据库查询,然后再设置缓存。

而在增删改的接口上,我是直接将缓存删除,等到调用分页查询数据的接口的时候再去重新设置一次缓存,以此保持数据的一致性。

具体可以看看下面的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// 调用/page接口,参数有PageNum、pageSize,还有其他非必须参数进行模糊查询
@GetMapping("/page")
public Result page(@RequestParam("pageNum") Integer pageNum ,
@RequestParam("pageSize") Integer pageSize,
@RequestParam(value = "username", required = false) String username,
@RequestParam(value = "email", required = false) String email,
@RequestParam(value = "phone", required = false) String phone){
IPage<User> page = new Page<>(pageNum , pageSize);
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.like(!Strings.isEmpty(username),"username" , username);
queryWrapper.like(!Strings.isEmpty(email),"email" , email);
queryWrapper.like(!Strings.isEmpty(phone),"phone", phone);

if(username == "" && email == "" && phone == ""){
// 查询缓存
String userKey = Constants.USER_PAGE_KEY + "_" + String.valueOf(pageNum);
String res = iRedisService.getString(userKey);
// 如果缓存存在,不为空,拿出来
if(!StrUtil.isBlank(res)){
// 把String类型转成JSON类型再返回
JSONObject data = JSONUtil.parseObj(res);
Integer nowSize = (Integer) data.get("size");
if(nowSize != pageSize){
// 页码发生变化的时候,清除缓存重新设置
iRedisService.flushRedis(userKey);
// 重新查询数据库
IPage<User> userIPage = userService.page(page, queryWrapper);
// 设置缓存
iRedisService.setString(userKey , JSONUtil.toJsonStr(userIPage));
return Result.success(userIPage);
}
return Result.success(data);
} else {
// 如果缓存不存在,查询数据库
IPage<User> userIPage = userService.page(page, queryWrapper);
// 设置缓存
iRedisService.setString(userKey , JSONUtil.toJsonStr(userIPage));
return Result.success(userIPage);
}
}

return Result.success(userService.page(page, queryWrapper));
}

实现方法

  1. 加入Redis序列化配置类,再Config里面设置相对于的序列化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
* redis序列化配置类
* @author AliveSeven 2023/01/30 18:00
*/
@Configuration
public class RedisConfig {
/**
* springboot 默认帮我们创建的RedisTemplate的key和value的序列化方式是jdk默认的方式,
* 我们有时候手动向redis中添加的数据可能无法被查询解析出来,所以我们需要修改序列化方式
* @param connectionFactory
* @return
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory connectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(connectionFactory);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
redisTemplate.setKeySerializer(stringRedisSerializer); //设置key的序列化方式
redisTemplate.setHashKeySerializer(stringRedisSerializer);//设置hash类型的数据的key的序列化方式

Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);//非final类型的数据才会被序列化
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);

redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);//设置value的序列化方式为json
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);

return redisTemplate;
}
}
  1. Redis的工具类里面加入下面的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* 根据模糊查询的key
* @param prefix
* @return keys
*/
public Set<String> getKeysByPre(String prefix){
return stringRedisTemplate.keys(prefix + "*");
}

/**
* 根据模糊查询的key进行批量删除
* @param prefix
* @return
*/
public void deleteByPre(String prefix){
Set<String> keys = stringRedisTemplate.keys(prefix + "*");
stringRedisTemplate.delete(keys);
}
  1. 然后传入要模糊搜索的key关键字,查询到的keys会放在一个列表里面,调用delete方法会删除对应的数据