1、缓存穿透:
缓存穿透:查询一个不存在的数据,MySQL查询不到的数据也不会直接写入缓存,就会导致每次请求都查询数据库,使得数据库访问压力过大,产生异常甚至宕机。
解决方案:
a、缓存空数据,查询返回的数据为空也要把这个空结果写进缓存 {key:1,value:null}
(优点:)这种方式简单方便(缺点:)但如果数据有很多都是null就会占用太多内存同时如果一个数据存入缓存为null,但之后在数据库中插入了这个数据,这样就会产生数据不一致的问题。
b、使用布隆过滤器。
开始时会从数据库中向redis批量缓存一些数据同时布隆过滤器也要缓存一些数据。
布隆过滤器使用bitmap:是一个以bit为单位的数组,数组中每个单元只存二进制数0或1。
作用:可以检索一个元素是否在一个集合中。
存数据:假设id为1的数据,通过多个hash函数获取hash值,根据hash计算数组对应的位置并把0改为1。
取数据:使用相同的hash函数获取hash值,并判断对应位置是否全为1。
但布隆过滤器是有误判发生的,如果一个元素多次hash计算后对应的数组的位置刚好是其他多个元素已经hash后的改为1的位置,这样就会产生误判,当然这个误判我们是可以设置的,在bloomFilter.tryInit(size ,0.05);中设置误判率为0.05。误判不可能不存在,我们只能改变误判率。数组越小误判率越大,数组越大误判率越小但随之而来的就是内存压力。
2、缓存击穿
缓存击穿:给某一个key设置了过期时间,当key过期时,恰好这个点对这个key有大量的并发请求,这些并发请求可能会瞬间压垮数据库。(一般我们在开发时对数据库的查询都是复杂的往往需要多表查询,这些查询会消耗很多时间,如果一瞬间有大量的请求则数据库会瞬间被压垮)
解决方案:
a、互斥锁
当缓存失效时,不立即去加载数据库,先使用redis的setnx去设置一个互斥锁,当操作成功返回时再进行加载数据库并回设缓存,否则重试get缓存的方法。
b、设置key逻辑过期
1、在设置key的时候,设置一个过期时间字段一块存入缓存中,不给当前key设置过期时间
2、当查询的时候,从redis取出数据后判断时间是否过期
3、如果过期则开通另外一个线程进行数据同步,当前线程正常返回数据,这个数据不是最新的数据。
区别:
互斥锁是强一致性,但性能不高,毕竟需要等待锁的释放,也可能产生死锁问题;
key逻辑删除是高可用性,性能较高,但数据同步做不到强一致。
3、缓存雪崩
&spm=1001.2101.3001.5002&articleId=139999510&d=1&t=3&u=ee46c42775b54066a5960235bfa7414e)
1111

被折叠的 条评论
为什么被折叠?



