缓存穿透

缓存数据没有命中就会存在缓存穿透。
目标:避免攻击性穿透、并发更新穿透,让缓存数据的失效过程尽可能平滑。
方法:选择不同的缓存策略、缓存淘汰算法。

第一种场景:
利用不存在的key攻击应用
过程:每次请求会先检查缓存中是否存在,如果存在返回缓存内容,如果不存在就回源,然后再将结果缓存。如果查询的某个数据在缓存中一直不存在,就会造成每一次请求都回源,这样缓存就失去了意义,流量大时,回源系统的压力就会非常大。
解决办法1:将不存在的key预先设定一个值,比如 unkownKey = “&&”。在返回这个&&值的时候,应用就可以认为这是不存在的key,再决定是否需要回源。
,设置一个很短的过期时间,最长不超过五分钟。原因如下:
缓存空对象会有两个问题:
(1)空值做了缓存,意味着缓存层中存了更多的键,需要更多的内存空间 ( 如果是攻击,问题更严重 ),比较有效的方法是针对这类数据设置一个较短的过期时间,让其自动剔除。
(2)缓存层和存储层的数据会有一段时间窗口的不一致,可能会对业务有一定影响。例如过期时间设置为 5分钟,如果此时存储层添加了这个数据,那此段时间就会出现缓存层和存储层数据的不一致,此时可以利用消息系统或者其他方式清除掉缓存层中的空对象。
解决方法2:使用布隆过滤器。将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。
,布隆过滤器使用场景:可以用来实现数据字典,进行数据的判重,或者集合求交集。对于原理来说很简单,位数组+k个独立hash函数。将hash函数对应的值的位数组置1,查找时如果发现所有hash函数对应位都是1说明存在,很明显这个过程并不保证查找的结果是100%正确的。同时也不支持删除一个已经插入的关键字,因为该关键字对应的位会牵动到其他的关键字。所以一个简单的改进就是counting Bloom filter,用一个counter数组代替位数组,就可以支持删除了。添加时增加计数器,删除时减少计数器。

第二种场景:
并发更新穿透
过程:一个缓存失效,并发访问高的情况会出现,多个进程同时查询DB,同时设置缓存,如果并发确实很大,也会造成回源系统压力过大。
解决办法1:对缓存查询加锁,如果key不存在,先加锁,再回源,将结果进行缓存,然后解锁。这种方式和第一种场景的解决方法类似,只不过利用锁的方式,会造成一部分请求等待。
解决办法2:双key。主key生成一个附属key来标识数据修改到期时间,快到时间的时候重新加载数据。附属key起到锁的功能。

参考:
《深入分布式缓存:从原理到实践》
https://blog.csdn.net/kongtiao5/article/details/82771694
https://blog.csdn.net/fei33423/article/details/79027790

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值