51mee - AI智能招聘平台Logo
模拟面试题目大全招聘中心会员专区

在教育平台中,课程列表、用户信息等常用数据需要缓存,请设计缓存策略,并说明如何避免缓存雪崩(大量缓存失效导致流量激增)。

好未来后端难度:中等

答案

1) 【一句话结论】:采用多级缓存(本地+Redis)结合TTL随机化、热点key加锁、主动预热策略,通过随机过期时间分散失效时间、对热点key加互斥锁避免并发更新,并提前加载热点数据,有效避免缓存雪崩。

2) 【原理/概念讲解】:缓存雪崩是指大量缓存key同时过期失效,导致流量集中到后端数据库。解决方案:

  • TTL随机化:为每个key的过期时间添加随机偏移量(如±10%),避免同时过期。类比:给每个蛋糕的保质期加一点随机时间,避免同时过期。
  • 热点key加锁:对高频访问的key(如课程列表、用户信息),使用分布式锁(如Redis SETNX)或互斥锁,确保同一时间只有一个请求去数据库查询并更新缓存,其他请求等待,避免并发更新导致缓存失效。
  • 多级缓存:本地缓存(如Java的ConcurrentHashMap)+Redis,本地缓存优先,减少Redis压力,同时本地缓存失效后快速回源到Redis。
  • 主动预热:系统启动或低峰期,将核心数据(如热门课程列表、用户信息)加载到缓存,减少首次访问的数据库压力。

3) 【对比与适用场景】:

策略定义特性使用场景注意点
TTL随机化为缓存key添加随机过期时间偏移分散失效时间,降低集中压力所有缓存key(尤其非热点)需动态调整偏移量,避免过期时间过长
热点key加锁对高频访问key加分布式锁,控制并发更新保证单线程更新缓存热门课程列表、用户信息等高频key锁粒度不宜过大,避免影响性能;锁超时处理
多级缓存本地缓存+Redis,本地优先回源减少Redis压力,快速响应高频访问数据(如课程列表)本地缓存与Redis数据一致性维护(如缓存失效后回源)
主动预热预先加载核心数据到缓存减少首次访问数据库压力系统启动、低峰期加载热点数据预热数据量需合理,避免占用过多资源

4) 【示例】(伪代码):
假设课程列表的缓存key为course_list,过期时间设为随机值(1-2小时),实现如下:

def get_course_list():
    # 1. 检查本地缓存
    local_cache = get_local_cache("course_list")
    if local_cache:
        return local_cache
    
    # 2. 检查Redis缓存
    redis_key = "course_list"
    redis_cache = redis.get(redis_key)
    if redis_cache:
        set_local_cache("course_list", redis_cache)
        return redis_cache
    
    # 3. 缓存未命中,加锁处理
    lock_key = f"course_list_lock"
    with redis_lock(lock_key, timeout=10):  # 分布式锁
        local_cache = get_local_cache("course_list")
        if local_cache:
            return local_cache
        redis_cache = redis.get(redis_key)
        if redis_cache:
            set_local_cache("course_list", redis_cache)
            return redis_cache
        
        # 数据库查询
        courses = db.query("select * from courses where is_hot=1")
        # 更新缓存
        redis.setex(redis_key, random_ttl(3600, 7200), json.dumps(courses))
        set_local_cache("course_list", json.dumps(courses))
        return courses

其中random_ttl函数生成1-2小时的随机过期时间,redis_lock是Redis分布式锁实现(如Redlock)。

5) 【面试口播版答案】:
“面试官您好,针对教育平台课程列表、用户信息等常用数据的缓存策略,我会从多级缓存、TTL随机化、热点key加锁、主动预热这几个方面设计,并避免缓存雪崩。首先,采用本地缓存(如Java的ConcurrentHashMap)+Redis的多级缓存架构,本地缓存优先,减少Redis压力。其次,对缓存key设置随机过期时间(比如课程列表的过期时间在1-2小时之间随机),避免大量key同时失效。对于高频访问的热点key(如热门课程列表),使用Redis分布式锁(如SETNX)保证同一时间只有一个请求去数据库查询并更新缓存,其他请求等待,防止并发更新导致缓存失效。另外,系统启动或低峰期会主动加载核心数据到缓存(如热门课程列表),减少首次访问的数据库压力。通过这些措施,可以有效分散缓存失效时间,避免流量激增导致的雪崩问题。”

6) 【追问清单】:

  • 追问1:为什么本地缓存和Redis需要配合?本地缓存的作用是什么?
    回答要点:本地缓存用于快速响应高频请求,减少Redis压力;本地缓存失效后回源到Redis,保证数据一致性。
  • 追问2:TTL随机化的具体实现方式?比如偏移量如何计算?
    回答要点:为每个key的过期时间添加随机偏移量(如±10%),例如课程列表的过期时间设为3600秒(1小时)±10%的随机值,避免同时过期。
  • 追问3:热点key加锁时,锁的粒度如何选择?比如锁整个key还是锁部分?
    回答要点:锁粒度不宜过大,应针对具体业务,比如课程列表的key加锁,避免影响其他课程查询;锁超时时间需合理,防止死锁。
  • 追问4:主动预热的作用?什么时候执行?
    回答要点:主动预热减少首次访问的数据库压力,提升用户体验;通常在系统启动时或低峰期(如凌晨)执行,加载热门数据到缓存。
  • 追问5:如果缓存失效后,数据库查询结果有变化怎么办?如何保证数据一致性?
    回答要点:可以通过缓存失效后回源,或者设置缓存过期时间,让缓存自然过期,同时结合版本号或时间戳保证数据一致性(如查询时带时间戳,避免脏读)。

7) 【常见坑/雷区】:

  • 坑1:只考虑TTL随机化,忽略热点key的并发更新问题,导致并发时多个线程同时去数据库查询并更新缓存,引发雪崩。
  • 坑2:本地缓存与Redis数据不一致,比如本地缓存未及时更新,导致返回旧数据。
  • 坑3:过期时间设置不合理,比如过期时间太短导致频繁回源,太长导致数据过时。
  • 坑4:未考虑缓存穿透问题,比如恶意请求导致大量无效key查询数据库。
  • 坑5:熔断降级未提及,当缓存雪崩时,系统如何降级(如返回默认数据或空列表)。
51mee.com致力于为招聘者提供最新、最全的招聘信息。AI智能解析岗位要求,聚合全网优质机会。
产品招聘中心面经会员专区简历解析Resume API
联系我们南京浅度求索科技有限公司admin@51mee.com
联系客服
51mee客服微信二维码 - 扫码添加客服获取帮助
© 2025 南京浅度求索科技有限公司. All rights reserved.
公安备案图标苏公网安备32010602012192号苏ICP备2025178433号-1