缓存穿透:

指查询一个一定不存在的数据,由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义。在流量大时,可能DB就挂掉了,要是有人利用不存在的key频繁攻击我们的应用,这就是漏洞。
解决方式:最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。另外也有一个更为简单粗暴的方法(我们采用的就是这种),如果一个查询返回的数据为空(不管是数据是不存在,还是系统故障),我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟(查空后插入了数据问题,和其他问题)。
**

缓存击穿:

对于一些设置了过期时间的key,这些key可能在某个时间点被超高并发的访问。如果这些key在过期的时候,恰好在这个时间点对这个Key有大量的并发请求过来,这些请求发现缓存过期会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮。
解决方式:使用互斥锁,就是在缓存失效的时候(判断拿出来的值为空),不是立即去load db,而是先使用缓存工具Redis的SETNX「SET if Not Exists」(或者Memcache的ADD)去set一个mutex key,当操作返回成功时,再进行load db的操作并回设缓存;否则,就重试整个get缓存的方法。伪代码

  1. func get(key string) string {
  2. val := redis.get(key)
  3. if value == redis.Nil { //代表缓存值过期
  4. //设置3min的超时,防止del操作失败的时候,下次缓存过期一直不能load db
  5. if err := redis.setnx(key_mutex, 1, 3 * 60); err != nil { //代表设置成功
  6. value = db.get(key);
  7. redis.set(key, value, expire_secs);
  8. redis.del(key_mutex);
  9. } else { //这个时候代表同时候的其他线程已经load db并回设到缓存了,这时候重试获取缓存值即可
  10. time.Sleep(5*time.Second);
  11. get(key); //重试
  12. }
  13. } else {
  14. return value;
  15. }
  16. }

**

缓存雪崩:

和缓存击穿相似,由于设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到DB,DB瞬时压力过重崩溃。

解决方式:缓存失效时的雪崩效应对底层系统的冲击非常可怕。大多数系统设计者考虑用加锁或者队列的方式避免重入,保证并发请求的时候只有一个请求去访问DB,其他请求都在阻塞等待,从而避免失效时大量的并发请求落到底层存储系统上。这里分享一个简单方案就时讲缓存失效时间分散开,比如我们可以在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。

什么是缓存预热

缓存预热就是在系统启动的时候将相关的缓存数据加载到缓存系统,这样就避免了用户在做查询的时候先查询数据库然后在将数据进行缓存的问题。
解决思路:
1、开发缓存刷新页面上线时手工操作下
2、数据量不大情况下可以在项目启动时自动加载进缓存
3、定时刷新缓存

什么是缓存更新

除了缓存服务器自带的缓存失效策略之外,我们还可以根据具体的业务需求进行自定义缓存淘汰策略,常见的策略有两种:
1、定时清理过去的数据(需要维护大量的key)
2、当用户请求时先判断这个请求所用到的缓存是否失效,失效的话则去进行数据库查询新的数据并更新至缓存系统(每次请求都要进行缓存判断,逻辑相对复杂)

什么是缓存降级

在高并发情况下,服务器出现问题或者非核心业务影响到核心流程的性能时,仍然需要保证服务可用,系统可以针对一些关键数据进行自动降级,也可以配置开关实现人工降级。

有什么方法可以使缓存降级?

日志级别设置预案:
1、一般:例如有些服务器偶尔发送网络抖动或者服务正在上线而超时,可以自动降级
2、警告:例如有些服务在一定时间内发生成功率有波动,可以自动降级成人工降级并发送告警
3、错误:例如系统可用率低于90%时,或者数据库连接池被打爆,或者访问量突然增大,导致系统的承受能力到达了阈值,此时可以根据情况自动降级或者人工降级
4、严重错误:因为某些特殊原因,此时需要紧急人工降级

在高并发情况下,如果redis服务不可用,可以直接返回默认值给用户,从而避免大量请求涌向数据库,避免数据库宕机,发生连锁反应,导致系统崩溃

什么是热点数据和冷数据

所谓热点数据就是经常被大量访问的数据
所谓冷数据就是频繁被修改的数据或者访问次数少之又少的数据

经常被访问的数据可以直接进行缓存,这样做可以避免高并发情况下大量请求访问数据库,造成数据库压力瞬间增大,对于频繁被更改并且频繁被访问的数据也可以进行缓存,减少数据库的压力(点赞数、分享数、收藏数)

Memcache与Redis的区别有哪些?

1、存储方式Memcache把数据全部存储在内存之中,断点后会挂掉,部署不能超过内存大小,Redis有部分存储在硬盘上,redis可以持久化数据。
2、数据支撑类型memcache所有的值都是简单的字符串类型,而redis拥有丰富的数据类型,提供了list、set、zset、hash等数据结构的存储。
3、使用的底层模型不一样,memcahce与redis的底层实现方式以及客户端之间通信的应用协议不一样,redis直接自己构建vm机制,因为一般的系统调用系统函数的时候会浪费一定的时间去请求
4、value值大小不一样,redis最大可以达到1gb,memcache只有1mb
5、redis的速度比memcache快很多
6、redis支持数据备份,即主从模式的数据备份