查询步骤图解
1.缓存穿透
查询请求一直向数据库查询,导致数据库压力过大,甚至奔溃
本质原因:查询的数据既不在缓存中,也不在数据库中
此时会出现:程序向缓存查询,发现无数据,遂向数据库查询,发现任然无数据,此时程序无法将数据写入缓存,导致后续的同类型的查询请求,会一直访问数据库;若请求数量极大,则会极大地增加数据库的压力,甚至让数据库奔溃
导致缓存穿透的可能原因:
1.业务层操作不当:将缓存与数据库的该数据都删除了
2.存在恶意攻击者:专门请求查询不存在的数据
1.添加校验参数
校验前段传递的参数,若不合理则直接返回,不予查询
2.设置空值缓存
将空数据的 key 设置为 null 存入缓存,如此一来查询该 key 将直接返回 null ,无需向数据库查询(该方法会产生数据的一致性问题,即缓存中的空值缓存尚未过期,但数据库中已有数据,此时查询返回的结果为空值;注:千万记得设置过期时间)
3.添加布隆过滤器(Bloom Filter)
Bloom Filter是由Howard Bloom在1970年提出的二进制向量数据结构,其具有空间和时间效率,被用来检测一个元素是否是集合的成员,检测结果分为在集合内(可能误判)与不在集合内(绝对准确)两种情况
2.缓存击穿
大量查询请求并发查询同一个热点 key ,而该 key 又正好失效,此时大量查询请求将涌向数据库,就像一面完整的墙上被凿穿了一个点,将导致数据库压力骤增,甚至奔溃
1.不过期
设置热点数据永不过期,通过定时任务刷新数据(注意使用场景)
2.分布式锁
对热点数据加分布式锁;当热点 key 过期后,第一个查询请求向数据库查询时,其余查询请求会被阻塞,直到锁被释放;后续进入的请求会直接从缓存中读取数据,因为第一个查询请求完成后,数据已被写入缓存
但是该方法会阻塞其他线程,会造成程序的吞吐量下降
3.缓存雪崩
缓存数据大量失效或缓存服务宕机,导致大量查询请求直接向数据库查询,导致数据库压力骤增,甚至奔溃;若无特殊处理办法就重启数据库,通常会出现:数据库奔溃---数据库重启---数据库奔溃---数据库重启······ 的循环
1.Redis集群(Redis Cluster)
通过部署Redis集群与哨兵集群,尽量避免因Redis服务器宕机而导致雪崩
如果缓存雪崩造成的原因是因为缓存服务宕机造成的,可以将redis
采用集群部署,可以使用 主从+哨兵 ,Redis Cluster 来避免 Redis 全盘崩溃的情况。若缓存雪崩是因为大量缓存因为失效时间而造成的,我们在批量往redis
存数据的时候,把每个Key的失效时间都加个随机值就好了,这样可以保证数据不会在同一时间大面积失效,或者设置热点数据永远不过期,有更新操作就更新缓存就可以了。
2.设置数据过期时间随机
避免因一时间内大量数据过期而导致雪崩
3.设置数据永不过期
理由同上,通过定时任务更新数据
若之前未考虑缓存雪崩的情况,但实际环境中确实发生了雪崩,可以通过以下方式补救:
1.ehcache本地缓存
2.Hystrix限流/降级