高并发场景下的缓存雪崩探析与应对策略

目录

一、问题描述

二、解决策略分析

(一)解决策略一:分散过期时间

(二)解决策略二:提前演练压测

[(三)解决策略三:cache高可用 + 后端数据库限流](#(三)解决策略三:cache高可用 + 后端数据库限流)

三、总结


干货分享,感谢您的阅读!

在高并发场景下,缓存作为前置查询机制,显著减轻了数据库的压力,提高了系统性能。然而,这也带来了缓存失效、增加回溯率等风险。常见的问题包括缓存穿透、缓存雪崩、热Key和大Key等。这些问题如果不加以处理,会影响系统的稳定性和性能。因此,采用有效的缓存策略,如缓存空结果、布隆过滤器、缓存过期时间随机化、多级缓存等,对于保障系统在高并发情况下的可靠性至关重要。本次我们将详细探讨缓存雪崩及其应对策略。

一、问题描述

缓存层挡在db层前面,抗住了非常多的流量,在分布式系统中,"everything will fails",缓存作为一种资源,当cache crash后,流量集中涌入下层数据库,称之为缓存雪崩。

造成这种问题通常有2种原因:

  1. 业务层面:大量的缓存key同时失效,失效请求全部回源到数据库,造成数据库压力过大崩溃。
  2. 系统层面:缓存服务宕机。

二、解决策略分析

(一)解决策略一:分散过期时间

业务层面的原因,主要是缓存key过期时间一致,造成同一时间,大量缓存key同时失效。针对这种问题的解决方案,主要是防止缓存在同一时间一起过期,如在设置的过期时间的基础上增加1-5分钟的随机值,使缓存失效时间比较均匀。通过这种方式,可以避免缓存key在同一时间失效,进而防止大量请求同时回溯到数据库。

java 复制代码
import java.util.Random;

public class CacheManager {
    private static final Random RANDOM = new Random();

    // 设置缓存值并增加随机过期时间
    public void setCache(String key, Object value, int baseExpirationTimeInSeconds) {
        int randomOffset = RANDOM.nextInt(300); // 1-5分钟的随机值,单位是秒
        int finalExpirationTime = baseExpirationTimeInSeconds + randomOffset;
        // 这里假设使用的是某个缓存框架的set方法
        cache.set(key, value, finalExpirationTime);
    }
}

(二)解决策略二:提前演练压测

系统在实际运行中可能会遇到各种性能瓶颈,提前演练和压测可以帮助发现这些瓶颈并进行优化。

在系统上线前,进行充分的压力测试和演练,找出系统的性能瓶颈,预估合适的系统存储和计算容量。根据压测结果,调整系统架构和配置,确保在高并发情况下系统能够稳定运行。

(三)解决策略三:cache高可用 + 后端数据库限流

  • 采用双缓存热备份方案来进可能提升缓存资源的可用性
  • 后端数据库限流(Hystrix),缓存层宕机,流量集中打到数据库,会再次让db崩溃。为保护这种情况下的db,在db层加入限流(Hystrix)

具体实现如下:

java 复制代码
public class CacheSupplier {

    @Qualifier(value = "tairCache")
    @Autowired
    private HACache tair;

    @Qualifier(value = "squirrelCache")
    @Autowired
    private HACache squirrel;

    @Autowired
    private CacheConfig cacheConfig;

    // 当前主备缓存引用,默认 master(squirrel) slave(celler)
    private CachePair cachePair;

    public CachePair getCachePair() {
        if (!cacheConfig.isCacheOn()) {
            return null;
        }
        if (cachePair != null && !cacheConfig.changed()) {
            return cachePair;
        }
        return updateCachePair();
    }

    private synchronized CachePair updateCachePair() {
        if (cachePair == null || cacheConfig.changed()) {
            cacheConfig.getConfigLock().lock();
            try {
                cachePair = createCachePair();
                cacheConfig.unchanged();
            } finally {
                cacheConfig.getConfigLock().unlock();
            }
        }
        return cachePair;
    }

    private CachePair createCachePair() {
        CachePair cp = new CachePair();
        cp.setMaster(selectCache(cacheConfig.getMasterCache(), tair, squirrel));
        if (cacheConfig.isSlaveOn()) {
            cp.setSlave(selectCache(cacheConfig.getSlaveCache(), squirrel, tair));
        }
        return cp;
    }

    private HACache selectCache(String cacheName, HACache defaultCache1, HACache defaultCache2) {
        if (CacheConfig.TAIR.equals(cacheName)) {
            return tair;
        } else if (CacheConfig.SQUIRREL.equals(cacheName)) {
            return squirrel;
        } else {
            return defaultCache1 != null ? defaultCache1 : defaultCache2;
        }
    }
}

三、总结

缓存雪崩作为高并发场景下的一个典型问题,严重威胁着系统的稳定性和性能。当缓存层失效或服务宕机时,大量请求会直接涌入数据库,造成数据库负载过重甚至崩溃。因此,采取有效的应对策略至关重要。

本文首先明确了缓存雪崩的定义及其两种主要成因,即业务层面的大量缓存key同时失效和系统层面的缓存服务宕机。针对这些成因,提出了三种解决策略:

  1. 分散过期时间:通过在设置的过期时间基础上增加随机值,使缓存失效时间均匀分布,避免大量请求同时回溯到数据库。
  2. 提前演练压测:通过充分的压力测试和演练,找出系统的性能瓶颈,并在系统上线前进行优化,确保系统在高并发情况下的稳定运行。
  3. cache高可用和后端数据库限流:采用双缓存热备份方案提升缓存资源的可用性,并在数据库层加入限流机制,防止缓存层宕机时流量集中打到数据库,进而保护数据库的稳定性。

这些策略各有优劣,结合具体业务场景和系统特点,灵活运用这些策略可以有效防止缓存雪崩。

相关推荐
難釋懷28 分钟前
分布式锁的原子性问题
分布式
消失的旧时光-19431 小时前
第十四课 · 实战篇:Redis 缓存系统落地指南(Spring Boot 从 0 到可用)
spring boot·redis·缓存
ai_xiaogui2 小时前
【开源前瞻】从“咸鱼”到“超级个体”:谈谈 Panelai 分布式子服务器管理系统的设计架构与 UI 演进
服务器·分布式·架构·分布式架构·panelai·开源面板·ai工具开发
凯子坚持 c2 小时前
如何基于 CANN 原生能力,构建一个支持 QoS 感知的 LLM 推理调度器
分布式
飞升不如收破烂~2 小时前
Redis 分布式锁+接口幂等性使用+当下流行的限流方案「落地实操」+用户连续点击两下按钮的解决方案自用总结
数据库·redis·分布式
森焱森2 小时前
详解 Spring Boot、Flask、Nginx、Redis、MySQL 的关系与协作
spring boot·redis·python·nginx·flask
无心水2 小时前
分布式定时任务与SELECT FOR UPDATE:从致命陷阱到优雅解决方案(实战案例+架构演进)
服务器·人工智能·分布式·后端·spring·架构·wpf
池央2 小时前
CANN Catlass 算子模板库深度解析:GEMM 核心优化、模板元编程与片上缓存策略的协同
缓存
茶杯梦轩2 小时前
从零起步学习Redis || 第七章:Redis持久化方案的实现及底层原理解析(RDB快照与AOF日志)
redis·后端