Redis缓存设计之缓存穿透、缓存雪崩
使用缓存的优缺点:
优点:
- 提高系统响应速度,加速读写,Redis将数全都存放在内存中,响应速度更快。
- 降低了后台的负载,减少了对后端的直接访问
缺点:
- 数据一致性问题,缓存层的数据与存储层的数据可能存在不一致的问题
- 维护复杂度高了,加入缓存后要同时处理缓存曾和持久层的代码逻辑
缓存穿透问题
缓存穿透就是指查询一个根本不存在的数据,导致很多请求直接穿过了缓存层直接到了持久层,,导致后端的负载加大。
导致缓存穿透的原因有以下几个:
- 业务逻辑代码本身就存在问题导致缓存穿透
- 受到了恶意的攻击以及网络爬虫等,导致大量请求缓存空命中
解决缓存穿透的方案:
1、缓存空数据
也就是说如果缓存层没有命中这个数据,查询持久层返回数据的同时也将空对象也缓存到缓存层,那么下一次请求就命中了。
public void getResult(String key)
{
String result = redisCache.get(key);
if(ValidationUtils.isEmpty(result))
{
result = DB.get(key);
redisCache.set(key,result);
if(ValidationUtils.isEmpty(result))
{
//设置失效时间
redisCache.expire(key,60*10);
}
returult;
}
else
{
//缓存命中
return result;
}
}
缓存空数据缺点:
- 缓存了空数据,也就说明有更多的key涌入了缓存层,也就需要消耗更多的内存,如果是恶意攻击那简直就是噩梦
- 缓存层与持久层的数据不一致问题,如果我缓存一个空对象并设置了失效时间为10分钟,那如果持久层真的持久化了这一数据,这5分钟内我缓存层和持久层的数据是不一致的。
2.布隆过滤器
基本思想就是在缓存层和持久层之前将存在的key用布隆拦截器保存起来做第一层拦截。如果布隆拦截器认为数据不存在就不访问持久层了,这样也解决了缓存击穿的问题。
缓存雪崩问题
在高并发的系统中缓存层负载了很大一部分的请求,降低的持久层的压力,如果缓存层由于某些原因停止服务了,那么所有的请求都将直接访问到持久层,由于持久层的处理速度性能远远不及缓存层,就可能导致持久层也会服务不可用,还有一种情况是大量的缓存数据在同一时刻失效了,也可能导致缓存雪崩。
解决缓存雪崩方案
- 1.保证缓存服务的高可用性,比如使用Redis哨兵监控Redis集群以及使用Redis Cluster等。即使单个节点宕机了,备用节点还能顶上去保证服务可用。
- 做二级缓存,当一级缓存停止服务,或大量失效时,由二级缓存顶住访问压力。
- 不同的key之间的失效时间设置不同保证数据失效均衡。