本文整理自黑马程序员相关资料
缓存穿透是指客户端请求的数据在缓存中和数据库中都部存在,这样缓存永远不会生效。因此这些请求都会穿过缓存,最终请求到数据库上,对数据库造成非常大的压力。
常见的解决方案有两种:
缓存空对象:当缓存和数据库都没有请求的数据时,将查询的key的value设置为NULL值缓存到Redis中,下次再查询时会在Redis中查到NULL值,请求不会到达数据库。
布隆过滤:在客户端与Redis中间加入布隆过滤器,如果布隆过滤器判断查询的数据不存在则直接拒绝。布隆过滤器如果判断不存在则一定不存在,判断存在则可能不存在。
缓存穿透的其他解决方案:
缓存雪崩是指在同一时段大量缓存key同时失效或者Redis服务宕机,导致大量请求到达数据库,给数据库带来巨大压力。
解决方案:
缓存击穿问题也叫热点key问题,就是一个高并发访问并且缓存重建业务比较复杂的key突然失效了,无数的请求访问会在瞬间给数据库带来巨大的冲击。
解决方案:
互斥锁:即只允许一个线程进行缓存重建,其他线程在缓存重建成功之前只能不断的重试。
逻辑过期:在热点key的value中设置逻辑过期时间,查询缓存的时候判断逻辑过期时间是否已经过期,如果已经过期,则获取互斥锁另开线程进行缓存重建。其他线程发现过期但获取互斥锁失败,返回过期数据。
两种解决方案的优缺点:
解决方案 | 优点 | 缺点 |
---|---|---|
互斥锁 | 因为没有设置逻辑过期时间,所以没有额外的内存消耗。保持一致性。实现简单 | 线程需要等待,性能受影响。可能有死锁风险 |
逻辑过期 | 线程无需等待,性能较好 | 不保证一致性。有额外的内存消耗。实现复杂 |