以redis为例,读取缓存的流程为读取缓存,若命中则返回,否则读数据库,若命中则返回,否则返回空
缓存穿透
如果把redis当做一道保护数据库的屏障(减轻数据库的压力),那么穿透顾名思义:直接穿过换缓存,视缓存于无物
缓存穿透是指缓存和数据库中都没有的数据,用户不断请求此类缓存和数据库都不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大直至奔溃
解决方法:
1 校验参数和合法性
2 如果缓存取不到的数据,在数据库中也没有取到,可以将key-value对写为key-null,同时设置缓存有效期,这样可以防止攻击用户反复用同一个id暴力攻击(有效期不宜过长,否则如果key对应的值真正被写入数据库,会造成数据不一致)
缓存击穿
同样的从名字上来分析,击穿有一种重复打击的感觉,即对一个特定数据高并发的访问,而此时缓存正好过期,导致大量请求直接查询数据库,就像把缓存击穿一样,与缓存穿透的区别在于后者数据库也不存在数据
解决方案:
1 设置热点数据永远不过期。
2 基于 redis or zookeeper 实现互斥锁,等待第一个请求构建完缓存之后,再释放锁,进而其它请求才能通过该 key 访问数据。
缓存雪崩
大量请求像雪崩了一样冲向数据库,原因有二
1 大量缓存同时过期
2 redis 宕机
都会造成大量请求一起查询数据库,从而搞死数据库,与缓存击穿的区别在于后者是单个缓存失效
解决方法:
1 缓存过期时间尽量分散
分散缓存的过期时间,尽量不出现大批缓存同时失效的场景
2 服务限流,降级保护
可以设置每秒的请求,有多少能通过组件,剩余的未通过的请求直接走降级