本文目录导读:

设计Python数据API缓存时,需要综合考虑缓存位置、缓存策略、数据一致性、失效机制等因素,以下是系统化的设计方案:
缓存层级架构
多级缓存模型(推荐)
客户端 → CDN缓存(可选) → 本地内存缓存 → 分布式缓存(Redis) → 数据库
各层级特点
| 层级 | 速度 | 容量 | 场景 |
|---|---|---|---|
| 本地内存 | 纳秒级 | 较小 | 高频、小数据量 |
| Redis | 微秒级 | 较大 | 中频、共享数据 |
| 数据库级 | 毫秒级 | 极大 | 低频、全量数据 |
核心缓存策略
1 缓存模式
旁路缓存模式(Cache-Aside)
from functools import wraps
import redis
import json
def cache_aside(ttl=300):
"""旁路缓存装饰器"""
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
cache_key = generate_cache_key(func.__name__, args, kwargs)
# 尝试从缓存读取
cached = redis_client.get(cache_key)
if cached:
return json.loads(cached)
# 执行原函数
result = func(*args, **kwargs)
# 写入缓存
if result is not None:
redis_client.setex(cache_key, ttl, json.dumps(result, default=str))
return result
return wrapper
return decorator
读写穿透(Read/Write Through)
class CacheThrough:
"""读写穿透缓存"""
def __init__(self, cache, db):
self.cache = cache
self.db = db
def get(self, key):
# 先读缓存
value = self.cache.get(key)
if value:
return value
# 缓存未命中,从DB读取并更新缓存
value = self.db.query(key)
if value:
self.cache.set(key, value, ttl=300)
return value
def set(self, key, value):
# 写入缓存和数据库
self.db.update(key, value)
self.cache.set(key, value, ttl=300)
2 缓存策略选择
# 1. 过期策略
TTL_STRATEGIES = {
'short': 60, # 1分钟(实时数据)
'medium': 600, # 10分钟(常用数据)
'long': 3600, # 1小时(不常变数据)
'forever': 86400 # 24小时(几乎不变数据)
}
# 2. 主动过期
def invalidate_cache(pattern):
"""清除匹配的缓存"""
for key in redis_client.scan_iter(match=pattern):
redis_client.delete(key)
# 3. 冷热数据分离
class TieredCache:
"""分级缓存"""
def __init__(self):
self.l1_cache = {} # 本地内存(热数据)
self.l2_cache = redis.Redis() # 远程缓存(温数据)
def get(self, key):
# L1检查
if key in self.l1_cache:
self.l1_cache[key]['hits'] += 1
return self.l1_cache[key]['data']
# L2检查
data = self.l2_cache.get(key)
if data:
self._promote_to_l1(key, data)
return data
return None
数据一致性方案
1 最终一致性(推荐)
class EventuallyConsistentCache:
"""最终一致性缓存"""
def __init__(self, cache, db, queue):
self.cache = cache
self.db = db
self.queue = queue # 消息队列
def update_data(self, key, new_value):
# 1. 更新数据库
self.db.update(key, new_value)
# 2. 异步清理缓存
self.queue.publish('cache_invalidate', key)
# 3. 或直接删除(淘汰策略)
self.cache.delete(key)
def get_with_consistency(self, key):
"""带一致性检查的读取"""
data = self.cache.get(key)
if data:
# 可选:检查版本号
if self._validate_version(data):
return data
return None
2 强一致性方案
class StrongConsistencyCache:
"""强一致性缓存(性能较低)"""
def __init__(self, cache, db, lock):
self.cache = cache
self.db = db
self.lock = lock # 分布式锁
def get(self, key):
# 读操作需要获取锁(读锁)
with self.lock.read_lock(key):
data = self.cache.get(key)
if not data:
data = self.db.query(key)
self.cache.set(key, data)
return data
def update(self, key, value):
# 写操作需要获取锁(写锁)
with self.lock.write_lock(key):
self.db.update(key, value)
self.cache.delete(key) # 或更新
高级缓存特性
1 缓存预热
class CacheWarmer:
"""缓存预热器"""
def __init__(self, cache, source_data):
self.cache = cache
self.source = source_data
def warm_up(self):
"""系统启动时预热热门数据"""
hot_keys = self._get_hot_keys()
for key in hot_keys:
data = self.source.get(key)
if data:
self.cache.set(key, data, ttl=3600)
def _get_hot_keys(self):
"""分析日志获取热键"""
# 分析访问日志
pass
2 缓存降级
class DegradedCache:
"""降级缓存"""
def __init__(self, primary_cache, fallback_cache):
self.primary = primary_cache
self.fallback = fallback_cache
def get(self, key):
try:
data = self.primary.get(key)
if data:
return data
except Exception:
# 主缓存宕机,降级到备用缓存
pass
# 尝试备用缓存
try:
return self.fallback.get(key)
except Exception:
return None # 或从数据库读取
监控与管理
1 缓存指标收集
class CacheMetrics:
"""缓存指标收集"""
def __init__(self, stats_client):
self.hits = 0
self.misses = 0
self.stats = stats_client # Prometheus等
def record_hit(self):
self.hits += 1
self.stats.increment('cache.hit')
def record_miss(self):
self.misses += 1
self.stats.increment('cache.miss')
@property
def hit_rate(self):
total = self.hits + self.misses
return self.hits / total if total > 0 else 0
2 缓存管理API
from flask import Blueprint, request
cache_blueprint = Blueprint('cache', __name__)
@cache_blueprint.route('/cache/clear', methods=['POST'])
def clear_cache():
"""手动清理缓存"""
pattern = request.json.get('pattern', '*')
count = redis_client.delete_pattern(pattern)
return {'cleared': count}
@cache_blueprint.route('/cache/status')
def cache_status():
"""缓存状态"""
info = redis_client.info()
return {
'used_memory': info['used_memory_human'],
'keys': info['db0']['keys'],
'hit_rate': calculate_hit_rate()
}
Go语言实现示例(可选)
// Go语言缓存实现
type CacheService struct {
localCache sync.Map
redis *redis.Client
metrics *MetricsCollector
}
func (c *CacheService) Get(key string) (interface{}, error) {
// L1: 本地缓存
if val, ok := c.localCache.Load(key); ok {
c.metrics.RecordHit("L1")
return val, nil
}
// L2: Redis缓存
val, err := c.redis.Get(ctx, key).Result()
if err == nil {
c.metrics.RecordHit("L2")
c.localCache.Store(key, val)
return val, nil
}
// 从DB查询
return c.loadFromDB(key)
}
最佳实践总结
- 缓存粒度:避免缓存整个大对象,分解为小对象
- Key命名:统一的命名规范,如
api:v1:users:123 - 过期策略:设置合理的TTL,避免缓存雪崩
- 监控告警:实时监控命中率、延迟、容量
- 降级方案:缓存不可用时不影响核心业务
- 版本控制:数据版本号或时间戳保证一致性
- 容量规划:预估数据增长,设置最大内存限制