$ redis-benchmark -t set,get -n 100000 -q
SET: 107758.62 requests per second, p50=0.239 msec
GET: 108813.92 requests per second, p50=0.239 msec
缓存击穿(失效); 缓存穿透; 缓存雪崩。
缓存击穿(失效)
解决方案
过期时间 + 随机值
预热
使用锁
public Object getData(String id) {
String desc = redis.get(id);
// 缓存为空,过期了
if (desc == null) {
// 互斥锁,只有一个请求可以成功
if (redis(lockName)) {
try
// 从数据库取出数据
desc = getFromDB(id);
// 写到 Redis
redis.set(id, desc, 60 * 60 * 24);
} catch (Exception ex) {
LogHelper.error(ex);
} finally {
// 确保最后删除,释放锁
redis.del(lockName);
return desc;
}
} else {
// 否则睡眠200ms,接着获取锁
Thread.sleep(200);
return getData(id);
}
}
}
缓存穿透
解决方案
缓存空值:当请求的数据不存在 Redis 也不存在数据库的时候,设置一个缺省值(比如:None)。当后续再次进行查询则直接返回空值或者缺省值。 布隆过滤器:在数据写入数据库的同时将这个 ID 同步到到布隆过滤器中,当请求的 id 不存在布隆过滤器中则说明该请求查询的数据一定没有在数据库中保存,就不要去数据库查询了。
“ 说下布隆过滤器的原理吧 ”
缓存雪崩
大量热点数据同时过期,导致大量请求需要查询数据库并写到缓存; Redis 故障宕机,缓存系统异常。
缓存大量数据同时过期
解决方案
Redis 故障宕机
解决方案
服务熔断和接口限流; 构建高可用缓存集群系统。
总结
缓存穿透指的是数据库本就没有这个数据,请求直奔数据库,缓存系统形同虚设。 缓存击穿(失效)指的是数据库有数据,缓存本应该也有数据,但是缓存过期了,Redis 这层流量防护屏障被击穿了,请求直奔数据库。 缓存雪崩指的是大量的热点数据无法在 Redis 缓存中处理(大面积热点数据缓存失效、Redis 宕机),流量全部打到数据库,导致数据库极大压力。
参考资料
https://segmentfault.com/a/1190000039688578
https://cloud.tencent.com/developer/article/1824584
https://learn.lianglianglee.com/
https://time.geekbang.org/
有道无术,术可成;有术无道,止于术
欢迎大家关注Java之道公众号
好文章,我在看❤️