高并发环境下的缓存问题 [TOC] ## 一、缓存穿透 ### 问题说明 缓存穿透是指查询一个一定不存在的数据,由于缓存未命中时就会查询数据库,数据库查不到数据时不会写入缓存,这就导致了这个缓存每次都会去数据库查询,造成了**缓存穿透**。 在流量较大时,或者利用不存在的缓存恶意频繁发起请求,数据库就会有宕机的风险。 ### 解决方案 #### 1. 布隆过滤器 将所有可能存在的数据哈希到一个足够大的`bitmap`中,一个一定不存在的数据会被这个`bitmap`拦截掉,从而避免了对底层数据库的查询压力。 **此方式是最常见的解决方案。** #### 2. 缓存空数据 如果一个查询返回的数据为空(不管是数据不存在,还是系统故障),仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。 **此方法比较简单粗暴。** ## 二、缓存雪崩 ### 问题说明 缓存雪崩是指在设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,导致所有的查询都落在数据库上,造成了缓存雪崩。 ### 解决方案 #### 1. 加锁阻塞 在缓存失效后,给一个请求该缓存的进程加锁,其他进程阻塞等待,由获取到锁的进程查询数据库后更新缓存。 #### 2. Cache Reload机制 配置`Cache Reload机制`,在缓存失效前主动触发更新缓存。 #### 3. 二级缓存(双缓存策略) 二级缓存也叫双缓存策略,配置两层缓存L1和L2,L1为原始缓存,L2为拷贝缓存,L1缓存失效时间短,L2缓存失效时间长,请求优先访问L1缓存,当L1未命中时给请求进程加锁,其他请求访问L2的缓存,让获取到锁的进程查询数据库后再更新L1和L2缓存。 #### 4. 调整失效时间 在设置缓存时,就让缓存的失效时间分布的均匀些,就不会出现大量缓存同时失效的情况。 ## 三、缓存击穿 ### 问题说明 缓存击穿的情况类似于缓存雪崩,区别在于雪崩是大量缓存同时失效,击穿是单个缓存在系统高并发时间失效。 ### 解决方案 #### 1. 主动刷新 由系统定义一个定时任务(job)主动去更新缓存。 例如,一个缓存中的数据过期时间是30分钟,那么job每隔29分钟定时刷新数据。 #### 2. 检查更新 将缓存的过期时间一起保存在缓存中,当缓存命中后拿到过期时间,若`过期时间 - 当前时间 <= 1分钟(或其他值)`,就主动更新缓存。 #### 3. 分级缓存 参考缓存雪崩解决方案。 注:该方式主要是通过避免缓存同时失效并结合锁机制实现。所以,当数据更新时,只能淘汰L1缓存,不能同时将L1和L2中的缓存同时淘汰。L2缓存中可能会存在脏数据,需要业务能够容忍这种短时间的不一致。而且,该方案可能会造成额外的缓存空间浪费。 2020-02-11 高并发 缓存 展开评论