redis之缓存雪崩,缓存击穿,缓存穿透

缓存雪崩

       大量key同时过期,打死数据库,

解决办法

     1)用锁/分布式锁或者队列串行访问

     2)缓存失效时间均匀分布,过期时间加入随机因子

缓存穿透

     频繁查询一个不存在的数据,由于缓存不命中,每次都要查询持久层,从而失去缓存的意义。

解决办法: 空对象和布隆过滤器

      持久层查询不到就缓存空结果,查询时先判断缓存中是否exists(key) ,如果有直接返回空,没有则查询后返回,注意insert时需清除查询的key,否则即便DB中有值也查询不到(当然也可以设置空缓存的过期时间)

空对象是首选方案,简单直接,碰到查询结果为空的键,放一个空值在缓存中,下次再访问就立刻知道这个键无效,不用发出SQL了。但“原文”也说了,存在如下问题:

第一,空值做了缓存,意味着缓存层中存了更多的键,需要更多的内存空间 ( 如果是攻击,问题更严重 ),比较有效的方法是针对这类数据设置一个较短的过期时间,让其自动剔除。

第二,缓存层和存储层的数据会有一段时间窗口的不一致,可能会对业务有一定影响。例如过期时间设置为 5 分钟,如果此时存储层添加了这个数据,那此段时间就会出现缓存层和存储层数据的不一致,此时可以利用消息系统或者其他方式清除掉缓存层中的空对象。

对于第一点,我还建议空值放在另外的缓存空间中,不宜与正常值共用空间,否则当空间不足时,缓存系统的LRU算法可能会先剔除正常值,再剔除空值——这个漏洞可能会受到攻击。

对于第二点,如果是Redis缓存,更新数据后直接在Redis中清除即可;如果是本地缓存,就需要用消息来通知其他机器清除各自的本地缓存了。(业界终于接受了用消息来同步缓存的设计思想,cheers! )大佬有一个小项目joint-cache-redis来简单地演示“用消息来同步多个机器的缓存”,而且在实践中发现Kafka可能比Redis MQ更适合于这个场景。

缓存击穿

热点key 失效,某个key访问非常频繁,当key失效的时候有大量线程来构建缓存,导致负载增加,系统崩溃

解决办法

1。使用锁,单机用synchronized,lock等,分布式用分布式锁。

2。缓存过期时间不设置,而是设置在key对应的value里。如果检测到存的时间超过过期时间则异步更新缓存。

3。在value设置一个比过期时间t0小的过期时间值t1,当t1过期的时候,延长t1并做更新缓存操作。

4。设置标签缓存,标签缓存设置过期时间,标签缓存过期后,需异步地更新实际缓存

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值