缓存击穿:
产生原因:缓存击穿的产生原因是 给某一个key设置了一个过期时间,而当这个时间正好过期的时候,对这个key有大量的并发请求过来,这些并发的请求就会直接访问DB,从而瞬间将DB压垮。
解决方案有以下两种:
1.互斥锁
这边来对互斥锁进行一个介绍: 首先是新开一个线程1,然后这边我们来进行缓存的查询,由于时间过期,查询不到导致未命中,然后在线程1中设置获取一个互斥锁,紧接着查询数据库来重建缓存数据,将数据重建好了之后,再返回写入缓存,最后释放锁。而互斥锁只能同时在一个线程中使用,所以当线程1没有释放锁的时候,线程2是用不了互斥锁的,只能一直重试,只有将线程1的互斥锁释放了之后,线程2才能缓存命中。
简述:当缓存失效的时候,不要立即去加载数据库,先用redis的setnx来设置一个互斥锁,当操作成功返回后再进行加载数据库的操作并且写入缓存,否则重试get缓存的方法。
优点:具有数据的强一致性 缺点:性能差,可能发生死锁
使用场景:和钱有关的项目系统。
2.逻辑过期
首先要先在redis缓存中多设立一个字段-过期时间。
在线程1中,来查询缓存,这时候发现设立的时间已经过期了,那么就直接用setnx来获取一个互斥锁,当操作成功之后,开启一个新的线程,(提示,这边线程1不需要等到线程2的重建成功,可以直接返回过期的数据)然后在线程2中进行查询数据库,重建缓存数据。操作完成之后将数据库内容写入缓存中,并且将新设的时间进行一个重置,最后释放锁。线程3在重建之前查询,所以还是返回过期数据,线程4是在重建之后,所以直接命中成功。
简述:1.在设置key的时候,设置一个过期时间字段一并放入缓存中,不给当前的key来设置过期时间。
2.在查询的时候,直接将新设置的过期时间字段从redis中取出,然后判断有没有过期。
3.如果过期了,就开通另外一个线程进行数据同步,当前线程正常返回过期数据。
优点: 高可用性,性能高 缺点: 数据不能保证强一致
使用场景: 大多数互联网项目