热点处理
场景
读写分离上线后,系统运行正常。
但某天,一个突发新闻事件发生了:
事件:某重大新闻突发
影响:
- 新闻 API 调用量暴增 10 倍
- Redis 中某个热点 key 被频繁访问
- Redis 单节点压力过大问题分析
我查了一下监控:
热点数据分布:
- 新闻"突发事件 A":占总请求的 60%
- 其他所有新闻:占 40%
Redis 访问统计:
- key "news:热点 A":每秒 5000 次访问
- 其他所有 key:每秒 3000 次访问
- 总计:每秒 8000 次问题:单个热点 key 导致 Redis 单点压力
解决方案
1. 多级缓存
class CacheManager:
"""多级缓存管理"""
def __init__(self):
# L1: 应用内存缓存(本地)
self.local_cache = {}
self.local_cache_ttl = {}
# L2: Redis 缓存(分布式)
self.redis_cache = redis.Redis()
def get(self, key):
"""获取数据(先本地后 Redis)"""
# 1. 检查本地缓存
if key in self.local_cache:
if time.time() < self.local_cache_ttl[key]:
return self.local_cache[key]
else:
del self.local_cache[key]
# 2. 检查 Redis 缓存
data = self.redis_cache.get(key)
if data:
# 更新本地缓存
self.local_cache[key] = data
self.local_cache_ttl[key] = time.time() + 60 # 本地缓存 1 分钟
return data
# 3. 缓存未命中
return None
def set(self, key, value, ttl):
"""设置数据(同时写入本地和 Redis)"""
# 写入本地缓存
self.local_cache[key] = value
self.local_cache_ttl[key] = time.time() + 60
# 写入 Redis
self.redis_cache.setex(key, ttl, value)
cache_manager = CacheManager()2. 热点 Key 分散
def get_hot_news(news_id):
"""获取热点新闻(使用 key 分散)"""
# 计算分散的 key
shard_count = 10 # 分散到 10 个 key
shard_index = hash(news_id) % shard_count
# 使用不同的 key
cache_key = f'news:hot:{shard_index}:{news_id}'
# 查询缓存
data = cache_manager.get(cache_key)
if data:
return data
# 调用 API
data = fetch_news_from_db(news_id)
# 写入缓存
cache_manager.set(cache_key, data, ttl=600)
return data3. 本地缓存预热
def preload_hot_data():
"""预热热点数据到本地缓存"""
# 获取热点新闻列表
hot_news = get_hot_news_list()
# 预加载到本地缓存
for news in hot_news:
cache_key = f'news:{news["id"]}'
# 从 Redis 获取
data = redis_client.get(cache_key)
if data:
# 存入本地缓存
cache_manager.local_cache[cache_key] = data
cache_manager.local_cache_ttl[cache_key] = time.time() + 60
# 定时预热:每 5 分钟
scheduler.add_job(
preload_hot_data,
'interval',
minutes=5,
id='preload_hot_data'
)效果验证
优化前
热点新闻查询:
- 全部请求打到 Redis
- Redis 单 key QPS: 5000
- Redis CPU: 80%优化后(多级缓存)
热点新闻查询:
- 80% 命中本地缓存(无网络开销)
- 15% 命中 Redis
- 5% 未命中,查询数据库
本地缓存命中率:80%
Redis QPS: 降到 1000
Redis CPU: 降到 30%本节小结
✅ 完成的工作:
- 实现了多级缓存
- 实现了热点 key 分散
- 实现了本地缓存预热
✅ 效果:
- Redis 压力降低 80%
- 响应时间进一步降低
- 系统更稳定
⚠️ 下一步:活动期间流量暴增 10 倍
🎯 下一步:活动期间流量暴增,如何削峰?
