缓存穿透
指查询一个不存在的数据,由于缓存中没有数据,所以这个查询请求会直接穿过缓存层,到达数据库层,造成了数据库的压力。攻击者可以通过构造恶意请求,使得缓存层无法命中任何数据,从而导致请求直接访问数据库,从而引起数据库压力过大。
缓存穿透-解决办法:在缓存中存储空结果的键,可以避免缓存穿透;或者使用延迟双写,在查询到数据库不存在该数据时,在缓存中也写入一个空结果的占位符,设置较短的过期时间。
缓存击穿
指缓存中某个热点数据失效,此时有大量并发请求同时访问这个失效的数据,导致这些请求直接访问数据库,造成数据库压力过大,甚至导致数据库崩溃。
缓存击穿-解决办法:可以设置热点数据的过期时间为随机时间,避免在同一时间大量数据同时失效;或者使用布隆过滤器(Bloom Filter)在查询前先判断查询的数据是否存在。
缓存雪崩
指缓存中大量的数据同时失效,导致大量请求直接访问数据库,造成数据库压力过大。
通常是由于缓存中大量的数据在同一时间失效,导致大量请求直接访问数据库。
缓存雪崩-解决办法:可以设置数据的过期时间为随机时间,避免大量数据在同一时间失效;或者设置缓存永不过期
除了缓存穿透、缓存击穿 和缓存雪崩,Redis缓存还可能遇到其他问题,例如:
缓存预热:
在系统上线后,需要将相关的缓存数据直接加载到缓存系统,以避免在后续的请求中需要查询数据库。可以通过缓存reload机制,预先去更新缓存,再即将发生大并发访问前手动触发加载缓存不同的key。
定时更新缓存策略:
对于实效性要求不高的缓存,可以使用定时任务更新或移除缓存。
设置不同的过期时间:
让缓存失效的时间点尽量均匀,避免大量缓存数据同时过期。
双层缓存策略:
C1为原始缓存,C2为拷贝缓存,C1失效时,可以访问C2,C1缓存失效时间设置为短期,C2设置为长期。
加锁排队 mutex互斥锁解决:
Redis的SETNX去set一个mutex key,当操作返回成功时,再进行加载数据库的操作并回设缓存,否则,就重试整个get缓存的方法。