Redis键值序列化和缓存的问题
1.springboot整合Redis的键值序列化问题
为什么要键值序列化?
不同平台之间的数据传输
Redis的序列化到底是什么?
简单的说,就是key和value存储到redis中的形式,这个形式是自己可以定义的
1.自定义一个序列化器
//自定义序列化器,就是放在redis中键和值的形式
public class MySerialize implements RedisSerializer {
private Class clazz;
public MySerialize(Class clazz){
this.clazz=clazz;
}
@Override
public byte[] serialize ( Object o ) throws SerializationException {
if (o==null){
return null;
}
// 将java对象转化成json字符串
String s = JSON.toJSONString(o);
return s.getBytes(Charset.forName("UTF-8"));
}
@Override
public Object deserialize ( byte[] bytes ) throws SerializationException {
if (bytes==null){
return null;
}
String str = new String(bytes);
// 将String类型的数据,转化成java对象
Object o = JSON.parseObject(str, clazz);
return o;
}
}
2.编写配置文件
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory){
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
// 设置连接工厂
redisTemplate.setConnectionFactory(redisConnectionFactory);
// 设置序列化器
redisTemplate.setKeySerializer(new StringRedisSerializer());
// 设置值的序列化器
redisTemplate.setValueSerializer(new MySerialize(Object.class));
//在Redis着有提供json格式的的序列化器
// redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));
return redisTemplate;
}
3.测试代码
@Autowired
private RedisTemplate redisTemplate;
//代码
redisTemplate.opsForValue().set("user",new User(1,"wangzi","123"));
2.Redis中的常见问题
1.缓存穿透
简单来说,就是服务器向客户端请求数据的时候,先去redis找数据,如果没找到,就会去数据库找,这样的话,每一个线程进来,都会去访问我们的数据库,这就会导致数据库压力增大,甚至崩溃,这就是缓存穿透
解决方案
当我们在redis没有找到数据,第一次访问数据库也没有找到数据时,直接将redis中的值设置为空值,下一次线程再来访问的时候,就不会访问我们的数据库,减少与数据库的交互,避免缓存穿透
2.Redis下的缓存雪崩
我们的客户端向redis发送请求的时候,redis集群突然崩溃,或者说,同一时间大量的key同时过期,那么所有的请求都会访问数据库,数据库的压力就会特别大,甚至崩溃,这就引起了Redis的缓存雪崩
解决方案:
针对大量的key在某一个时间同时过期
在计算出key的过期时间之后,动态的加上一个范围内的随机数,作为最终key的过期时间,错峰过期
针对集群出现问题
做缓存的高可用,缓存做一个降级处理
做redis的缓存预热:在使用缓存数据之前,先将数据库中要缓存的数据放入redis中
3.脑裂问题
客户端向redis写入数据的时候,主服务器突然崩溃,那么就会有一台从服务器成为新的主服务器,但是以前的主服务器的数据不能同步,这就是redis的脑裂问题