缓存击穿
缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个redis键进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库。
解决方案
1.设置经常是用的redis键永远不过期。
2.加互斥锁
根据key获取value值为空时,锁上,从数据库中load数据后再释放锁。若其它线程获取锁失败,则等待一段时间后重试。这里要注意,分布式环境中要使用分布式锁,单机的话用本地锁.
3.接口限流与熔断、降级
重要的接口一定要做好限流策略,防止用户恶意刷接口,同时要降级准备,当接口中的某些服务不可用时候,进行熔断,失败快速返回机制。
缓存雪崩
缓存雪崩,是指在某一个时间段,缓存集中过期失效。
解决方案
1.动态修改到期时间
缓存失效时的雪崩效应对底层系统的冲击非常可怕!大多数系统设计者考虑用加锁或者队列的方式保证来保证不会有大量的线程对数据库一次性进行读写,从而避免失效时大量的并发请求落到底层存储系统上。还有一个简单方案就时讲缓存失效时间分散开,比如我们可以在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。
2.采用线程池,代码加锁
3.使用cluster方式部署
这样只要增加服务器的数量就会有效的控制缓存雪崩
4.给每一个缓存数据增加相应的缓存标记,记录缓存是否失效,如果缓存标记失效,则更新数据缓存
缓存穿透
缓存穿透,是指查询一个数据库一定不存在的数据。正常的使用缓存流程大致是,数据查询先进行缓存查询,如果key不存在或者key已经过期,再对数据库进行查询,并把查询到的对象,放进缓存。如果数据库查询对象为空,则不放进缓存。此时,若攻击者抓住这个漏洞不断请求数据库,就会对数据库造成压力,甚至压垮数据库。
解决方案
1.布隆过滤器
有很多种方法可以有效地解决缓存穿透问题,最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被 这个bitmap拦截掉,从而避免了对底层存储系统的查询压力
2.对于redis获取数据加锁
一般不会采用,会极大的降低并发
3.使用线程池,规定最大的连接数;
可能存在的问题是,当连接数大于配置的连接数时,会导致多余的客户端无法与redis进行链接
4.设置空缓存
如果一个查询返回的数据为空(不管是数 据不存在,还是系统故障),我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟, 但是这样会存储很多垃圾数据