1.缓存穿透是什么?
缓存穿透,是指查询一个数据库一定不存在的数据
问题:
想象一下,如果查询传入的参数是-1,会怎么样??
这个-1,一定是不存在的对象。当每次用-1 去查询数据库的时候,每次查询的结果都为空,每次又都不会进行缓存,假如有恶意攻击,就可以利用这个漏洞,对数据库造成压力,甚至压垮数据库。即便是采用UUID,也是很容易找到一个不存在的key,进行攻击。
解决办法:
采用缓存空值的方式
如果从数据库查询的对象为空,也放入缓存,但是设置缓存的时间较短,比如设置为60s
三、缓存雪崩
1.缓存雪崩是什么??
缓存雪崩:在某一个时间段,缓存集中过期失效
问题:雪崩的原因之一:
在写文本的时候,马上就要到双十二零点,很快就会迎来一波抢购,这波商品比较集中的放入了缓存,假设缓存一个小时,那么到了凌晨一点钟的时候,这批商品的缓存就都过期了,而对这批商品的访问查询,都落到了数据库上,对于数据库而言,就会产生周期性的压力波峰。
解决办法:
采用不同分类商品,缓存周期不同。
在同一分类中的商品,加上一个随机因子,这样尽可能的分散缓存过期时间。
热门类的商品缓存时间长一些,冷门类目的商品缓存时间短一些,也能节省缓存服务的资源。
其实,集中过期倒不是非常致命
比较致命的缓存雪崩,是缓存服务器某个节点宕机或断网
而缓存服务节点的宕机,对数据库服务器造成的压力是不可预知的,很有可能瞬间就把数据库压垮
四、缓存击穿
1.什么是缓存击穿
缓存击穿,是指一个key非常热点,不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就击破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。
解决办法:
1.让主打商品缓存永不过期。
2..使用互斥锁,就是在缓存失效的时候(判断拿出来的值为空),不是立即去查询数据库,而是先使用缓存工具的某些带成功操作返回值的操作比如redis的SETNX,去set一个mutex key,当操作返回成功时,在进行查询数据库的操作并回设缓存;否则就重试整个get缓存的方法;
五、缓存并发
1.缓存并发是什么??
如果网站并发访问量高,一个缓存如果失效或者不存在,可能出现多个进程同时直接获取DB数据,这时会对DB造成很大的访问压力
原因: 1. 缓存过期或者在更新或者不存在;
2. 同时有大量的并发请求该key;
3. 如果缓存更新,对某个key有大量的并发请求,此时请求获得的结果可能是更新之前 或者更新之后,从而导致 ”缓存一致性“的问题出现。
解决办法:
由于缓存并发问题一般发生在查询期间,而且问题出在缓存更新时的高并发时刻,思路上,就可以在这个时候,对key加锁 (对缓存查询加锁,如果key不存在,就加锁,然后查DB后写入缓存,然后加锁)
六、缓存一致性
1.缓存一致性是什么??
当数据时效性要求很高时,需要保证缓存中的数据与数据库中的保持一致,需要保证缓存节点和副本中的数据也保持一致,不能出现差异现象(集群同步)
原因:对同一个数据进行读写,在数据库层面并发的读写并不能保证完成顺序;
解决方案:先更新数据库,成功后,让缓存失效
七、缓存删除
前提:缓存设置了一个过期时间,过期后需要对这批key进行删除,因为缓存大小有限
定期删除:默认每100ms随机抽取一些过期的key,检查是否过期,如果过期就删除。因为本身key非常多,所以做不到每100ms遍历所有key,不然cpu压力很大
惰性删除:靠定期删除还残留的key,当你再次去查询这个key的时候,删除这个key
问题:如果定期漏掉很多key,且长时间没去查询,导致key堆积在内存中
解决方案:
从已设置过期时间的数据集里挑选最近最少使用的数据淘汰;从已设置过期时间的数据集里挑选将要过期的数据淘汰;从已设置过期时间的数据集里挑选任意选择数据淘汰;在内存不足时,移除最近最少使用的数据;从数据集中任意淘汰数据;禁止驱逐数据;