- 缓存在大并发系统中的重要做用不言而喻。缓存属于内存操做,微秒或毫秒级别。在互联网公司绝对绕不过这个缓存。缓存有不少mc,redis等。这里描述的是redis.由于redis能够持久化,而mc纯内存,重启机器数据就没法找回。redis则还能够从新从磁盘中导入数据。缓存则又有绕不开的问题。那就是雪崩,击穿,穿透问题。
缓存雪崩:
-
- 现象:
影响轻则,查询变慢,重则当请求并发更高时,出来大面积服务不可用。
-
- 缘由:
同一时间缓存大面积失效,就像没有缓存同样,全部的请求直接打到数据库上来,DB扛不住挂了,若是是重要的库,例如用户库,那牵联就一大片了,瞬间倒一片。
-
- 案例:
电商首页缓存,若是首页的key所有都在某一时刻失效,恰好在那一时刻有秒杀活动,那这样的话就全部的请求都被打到了DB。并发大的状况下DB必然扛不住,没有其余降级之类的方案的话,DBA也只能重启DB,可是这样又会被新的流量搞挂。
-
- 解决方案:
批量往redis存数据的时候,把每一个key的失效时间加上个随机数,这样的话就能保证数据不会在同一个时间大面积失效。
缓存穿透:
-
- 现象与缘由:
就是指用户不断发起请求的数据,在缓存和DB中都没有,好比DB中的用户ID是自增的,可是用户请求传了-1,或者是一个特别大的数字,这个时候用户颇有可能就是一个攻击者,这样的功击会致使DB的压力过大,严重的话就是把DB搞挂了。由于每次都绕开了缓存直接查询DB
-
- 解决方案:
- 方法一:在接口层增长校验,不合法的参数直接返回。不相信任务调用方,根据本身提供的API接口规范来,做为被调用方,要考虑可能任何的参数传值。
- 方法二:在缓存查不到,DB中也没有的状况,能够将对应的key的value写为null,或者其余特殊值写入缓存,同时将过时失效时间设置短一点,以避免影响正常状况。这样是能够防止反复用同一个ID来暴力攻击。
- 方法三:正经常使用户是不会这样暴力功击,只有是恶意者才会这样作,能够在网关NG做一个配置项,为每个IP设置访问阀值。
- 方法四:高级用户布隆过滤器(Bloom Filter),这个也能很好地防止缓存穿透。原理就是利用高效的数据结构和算法快速判断出你这个Key是否在DB中存在,不存在你return就行了,存在你就去查了DB刷新KV再return。
缓存击穿:
-
- 现象与缘由:
跟缓存雪崩相似,可是又有点不同。雪崩是由于大面积缓存失效,请求全打到DB;而缓存击穿是指一个key是热点,不停地扛住大并发请求,全都集中访问此key,而当此key过时瞬间,持续的大并发就击穿缓存,全都打在DB上。就又引起雪崩的问题。
-
- 解决方案:
设置热点key不过时。或者加上互斥锁。
总结:
这就是三者的区别,差很少,但又有一些区别。由于缓存雪崩、穿透和击穿,是缓存最大的问题,要么不出现,一旦出现就是致命性的问题
通常避免以上状况发生咱们从三个时间段去分析下:redis
- 事前:Redis 高可用,主从+哨兵,Redis cluster,避免全盘崩溃。
- 事中:本地 ehcache 缓存 + Hystrix 限流+降级,避免** MySQL** 被打死。
- 过后:Redis 持久化 RDB+AOF,一旦重启,自动从磁盘上加载数据,快速恢复缓存数据。
扩展知识:
能够用限流组件,设置每秒的请求,有多少能经过组件,剩余的未经过的请求,怎么办?走降级!能够返回一些默认的值,或者友情提示,或者空白的值。
这样的好处就是:数据库绝对不会死,限流组件确保了每秒只有多少个请求能经过。 只要数据库不死,就是说,对用户来讲,3/5 的请求都是能够被处理的。 只要有 3/5 的请求能够被处理,就意味着你的系统没死,对用户来讲,可能就是点击几回刷不出来页面,可是多点几回,就能够刷出来一次。
摘抄自网络算法