Redis缓存击穿、缓存、缓存雪崩,redis高频面试题又来了

Redis缓存击穿、缓存、缓存雪崩,redis高频面试题又来了
最新回答
那一抹浅笑

2026-10-20 13:46:54

Redis缓存击穿、缓存穿透和缓存雪崩是使用Redis作为缓存系统时常见的三种问题,以下是它们的详细解释和应对策略:

  1. 缓存击穿(Cache Breakdown)

    原因:缓存击穿是指某个热点数据在缓存中过期,而此时有大量并发请求访问该数据,导致这些请求直接打到数据库上,造成数据库压力过大。

    应对策略:

    设置热点数据不过期:对于热点数据,可以设置永不过期或者设置较长的过期时间。

    互斥锁:使用分布式锁来保证只有一个线程去查询数据库并更新缓存,其他线程等待缓存更新完成。

    应用场景:商品秒杀活动、热门新闻详情页等。

    示例代码:

    import redisimport timefrom threading import Lock# 初始化Redis连接r = redis.StrictRedis(host='localhost', port=6379, db=0)lock = Lock()def get_data(key): # 尝试从缓存获取数据 value = r.get(key) if value is not None: return value # 加锁,防止缓存击穿 with lock: value = r.get(key) if value is not None: return value # 模拟从数据库获取数据 value = "database_value" r.setex(key, 3600, value) # 设置缓存,过期时间为1小时 return value# 测试函数if __name__ == "__main__": key = "hot_key" print(get_data(key))
  2. 缓存穿透(Cache Penetration)

    原因:缓存穿透是指查询一个不存在的数据,由于缓存中没有这个数据,每次请求都会直接打到数据库上,造成数据库压力过大。

    应对策略:

    布隆过滤器:在缓存之前增加一层布隆过滤器,快速判断数据是否存在。

    缓存空值:对于查询结果为空的数据也进行缓存,设置较短的过期时间。

    应用场景:用户登录验证、商品查询等。

    示例代码:

    import redisfrom pybloom_live import BloomFilter# 初始化Redis连接和布隆过滤器r = redis.StrictRedis(host='localhost', port=6379, db=0)bloom = BloomFilter(capacity=100000, error_rate=0.001)def get_data(key): # 检查布隆过滤器 if key not in bloom: return None # 尝试从缓存获取数据 value = r.get(key) if value is not None: return value # 模拟从数据库获取数据 value = "database_value" if key == "existing_key" else None if value is not None: r.setex(key, 3600, value) # 设置缓存,过期时间为1小时 else: r.setex(key, 60, "") # 缓存空值,过期时间为1分钟 return value# 测试函数if __name__ == "__main__": keys = ["existing_key", "non_existing_key"] for key in keys: bloom.add(key) # 将存在的键添加到布隆过滤器中 print(f"{key}: {get_data(key)}")
  3. 缓存雪崩(Cache Avalanche)

    原因:缓存雪崩是指大量缓存同时过期,导致大量请求直接打到数据库上,造成数据库压力过大。

    应对策略:

    缓存预热:在缓存即将过期前主动刷新缓存。

    随机过期时间:为缓存设置不同的过期时间,避免同一时间大量缓存同时过期。

    限流降级:在缓存失效后,通过限流和降级措施保护数据库。

    应用场景:定时任务刷新缓存、批量处理数据等。

    示例代码:

    import redisimport randomimport time# 初始化Redis连接r = redis.StrictRedis(host='localhost', port=6379, db=0)def set_cache_with_random_expiry(key, value): expiry = random.randint(300, 3600) # 随机设置过期时间,范围在5分钟到1小时之间 r.setex(key, expiry, value)def refresh_cache(): keys = ["key1", "key2", "key3"] for key in keys: value = f"new_value_for_{key}" set_cache_with_random_expiry(key, value) print(f"Refreshed cache for {key}")# 测试函数if __name__ == "__main__": refresh_cache() while True: time.sleep(1) # 模拟持续运行的服务

这些策略可以帮助你在使用Redis作为缓存系统时,有效地应对缓存击穿、缓存穿透和缓存雪崩等问题。