缓存穿透:
- 什么叫缓存穿透: 缓存穿透是指查询一个一不存在的数据。
- 例如:从缓存redis没有命中,需要从mysql数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,造成缓存穿透。
- 解决方法:
- 1.缓存空. 如果查询数据库也为空,直接设置一个默认值 比如 空值(空字符,空数组, 空对象) 存放到缓存,这样第二次到缓冲中获取就有值了,而不会继续访问数据库。设置一个过期时间60s或者维护有值的时候将缓存中的值替换掉即可。可以给key设置一些格式规则,然后查询之前先过滤掉不符合规则的Key。
- 2.布隆过滤器:原理就是一个对一个key进行k个hash算法获取k个值,在比特数组中将这k个值散列后设定为1,然后查的时候如果特定的这几个位置都为1,那么布隆过滤器判断该key存在。
布隆过滤器可能会误判,如果它说不存在那肯定不存在,如果它说存在,那数据有可能实际不存在;
Redis的bitmap只支持2^32大小,对应到内存也就是512MB,误判率万分之一,可以放下2亿左右的数据,性能高,空间占用率及小,省去了大量无效的数据库连接。
因此我们可以通过布隆过滤器,将Redis缓存穿透控制在一个可容范围内.
缺点:
- 存在误判率.
- 做不到移除删除的概念. 因为多个数据存在于一个位置.
缓存雪崩:
- 什么是缓存雪崩: 缓存key大量失效后,大量请求转向到数据库
- 做不到完全解决,只能缓解 这一现象.提前做好防护措施.
- 永不过期
- 缓存key的过期时间错开. 避免同一时间失效.
- 多缓存结合. 结合其他缓存.
- 使用 三方的redis 比如 阿里云. 用钱解决
批量操作
public List<Object> multiGet(List<String> keys) {
try {
return redisTemplate.opsForValue().multiGet(keys);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public List<Object> batchGet(List<String> keys) {
List<Object> objects = redisTemplate.executePipelined(new RedisCallback<String>() {
@Override
public String doInRedis(RedisConnection redisConnection) throws DataAccessException {
StringRedisConnection connection = (StringRedisConnection) redisConnection;
for (String key : keys) {
connection.get(key);
}
return null;
}
});
return objects;
}
public List<Object> batchGet(List<String> keys) {
List<Object> objects = redisTemplate.executePipelined((RedisCallback<String>) redisConnection -> {
StringRedisConnection connection = (StringRedisConnection) redisConnection;
for (String key : keys) {
connection.get(key);
}
return null;
});
return objects;
}