缓存
简介
简而言之,即是数据存储的缓冲区。使用缓存之后,可以减轻访问数据库的压力,显著的提升系统的性能。
使用缓存的一般流程如下:

缓存通常有两种:
- 服务器主集本身的内存缓存,也就是我们说的二级缓存。
- 相比于缓存中间件性能更好。但只能应用于本机,若系统分布式部署,会存在数据不一致的问题。
- 缓存中间件,比如:Redis、Memcached等
- 适用于分布式缓存,解决分布式数据一致性问题
有些业务场景,分布式缓存和二级缓存可以一起使用
缓存带来的问题
1. 缓存雪崩
缓存雪崩指的是当某一个时间段出现大规模的缓存失效的情况,此时大量的并发请求直接命中在数据库上面,导致数据库压力巨大,甚至宕机。
分析
造成缓存雪崩的关键在于在同一时间段大量的key失效。出现这个问题的可能性:1. 缓存宕机。2. 采用了相同的过期时间。
解决方式
- 过期时间采用随机值
- 若真的发生了缓存雪崩,使用熔断机制。当流量到达一定阈值,直接返回“系统拥挤”之类的提示,防止过多的请求打在数据库上。至少能保证一部分用户是可以正常使用,其他用户多刷新几次也能得到结果。
- 提高数据库的容灾能力,可以使用分库分表,读写分离的策略。
- 防止Redis缓存宕机导致缓存雪崩的问题,可以搭建Redis集群,提高Redis的容灾性。

2. 缓存击穿
缓存击穿指的是大量并发集中访问某一个 key,突然这个 Key 缓存失效了,导致大并发一时间全部命中在数据库上。
与缓存雪崩对比
- 缓存雪崩是大量的 key 失效导致的
- 而缓存击穿是大规模访问一个失效的 key 导致的
分析
关键在于某个热点 key 失效了,导致大并发集中打在数据库上。
所以要从两个方面解决,第一是否可以考虑热点key不设置过期时间,第二是否可以考虑降低打在数据库上的请求数量。
解决方式
- 若业务允许,对热点 key 可以设置永不过期
- 使用互斥锁。当缓存失效时,只有拿到锁才可以查询数据库,降低了在同一时刻命中在数据库上的请求。
- 可以对 Key 进行加锁
- 相应的,加锁会导致系统性能降低。
3. 缓存穿透
假如请求的 key 是在缓存中是不存在的,那缓存查不到就会去数据库查询。如果有大量这样的请求,这些请求像“穿透”了缓存一样直接命中在数据库上,这种现象就叫做缓存穿透。

分析
关键点是缓存中查不到 Key,这些 key 是不存在的
PS:说明了边界安全的重要性。应该做好参数检验,外界不可信
解决方式
-
把无效的Key存入缓存。如果缓存查不到,数据库也查不到,可以把这个 Key 值存入缓存,并设置value=“null”,当下次再通过这个Key 查询时就不需要再查询数据库。
- 弊端是,假如传进来的这个不存在的Key值每次都是随机的,那这种做法无意义。
-
使用布隆过滤器。布隆过滤器的作用是某个 key 不存在,那么就一定不存在,它说某个 key 存在,那么很大可能是存在(存在一定的误判率)。因此,可以在缓存之前再加一层布隆过滤器,在查询的时候先去布隆过滤器查询 key 是否存在,如果不存在就直接返回。
- 参考:https://cloud.tencent.com/developer/article/1687510