网络日志

【Java面试】怎么防止缓存击穿的问题?

“怎么防止缓存击穿?”

这是很多一二线大厂面试的时候考察频率较高的问题。

在并发量较高的系统中,缓存可以提升数据查询的性能,还能缓解后端存储系统的并发压力。可谓是屡试不爽的利器。

我把这个问题的回答,整理到了一个20W字的面试文档里面。大家可以私信我领取。

下面看看高手的回答。高手:

在实际应用中,我们会在程序和数据库之间增加一个缓存层。

一方面是为了提升数据检索效率,提升程序性能,另一方面是为了缓解数据库的并发压力。

缓存击穿,表示请求因为某些原因全部打到了数据库,缓存并没有起到流量缓冲的作用。

我认为有2种情况会导致缓存击穿。

在Redis里面保存的热点key,在缓存过期的瞬间,有大量请求进来,导致请求全部打在数据库上。
客户端恶意发起大量不存在的key的请求,由于访问的key对应的数据本身就不存在,所以每次必然都会穿透到数据库,导致缓存成为了摆设。

总之,当Redis承担了流量缓冲功能的时候,就需要考虑到Redis失效导致并发压力过大对后端存储设备造成冲击的问题。

因此,我认为可以通过几种方法来解决。

对于热点数据,我们可以不设置过期时间,或者在访问数据的时候对数据过期时间进行续期。

对于访问量较高的缓存数据,我们可以设计多级缓存,尽量减少后端存储设备的压力。

使用分布式锁,当发现缓存失效的时候,不是先从数据库加载,而是先获取分布式锁,获得分布式锁的线程从数据库查询数据后写回到缓存里面。

后续没有获得锁的线程就只需要等待和重试即可。

这个方案牺牲了一定的性能,但是确保护了数据库避免被压垮。

对于恶意攻击类的场景,可以使用布隆过滤器,应用启动的时候把存在的数据缓存到布隆过滤器里面。

每一次请求进来的时候先访问布隆过滤器,

如果不存在,则说明这个数据一定没有在数据库里面,就没必要再去访问数据库了。

另外,我们在整个缓存架构设计中,除了尽可能避免缓存穿透的问题,还需要从全局视角做整体考虑

比如业务隔离、多级缓存、部署隔离、安全性考虑等。总结

在我看来,很多面试题,其实更多的是考察求职者的技术底蕴以及思维边界,有些问题不一定会有答案,或者说在面试的过程中不一定立刻能提出非常好的解决办法我们只需要说大概的方向和思路即可。