跳到主要内容

缓存策略

问题

Python 中有哪些缓存方案?如何选择?

答案

functools.lru_cache(内存缓存)

from functools import lru_cache, cache

# lru_cache:限制缓存大小的 LRU 缓存
@lru_cache(maxsize=256)
def fibonacci(n: int) -> int:
if n < 2:
return n
return fibonacci(n - 1) + fibonacci(n - 2)

# cache:无限制缓存(Python 3.9+)
@cache
def expensive_compute(x: int, y: int) -> int:
return x ** y

# 查看缓存统计
print(fibonacci.cache_info())
# CacheInfo(hits=98, misses=100, maxsize=256, currsize=100)

# 清除缓存
fibonacci.cache_clear()

TTL 缓存

from cachetools import TTLCache, cached

# 最多 1000 项,60 秒过期
ttl_cache = TTLCache(maxsize=1000, ttl=60)

@cached(ttl_cache)
def get_config(key: str) -> str:
return fetch_from_db(key)

Redis 缓存

import redis.asyncio as redis
import json

r = redis.from_url("redis://localhost")

async def get_user_cached(user_id: int) -> dict | None:
# 先查缓存
cached = await r.get(f"user:{user_id}")
if cached:
return json.loads(cached)

# 缓存未命中,查数据库
user = await fetch_user_from_db(user_id)
if user:
await r.setex(f"user:{user_id}", 300, json.dumps(user)) # 缓存 5 分钟
return user

async def invalidate_user(user_id: int):
await r.delete(f"user:{user_id}")

缓存装饰器

from functools import wraps

def redis_cache(ttl: int = 300, prefix: str = "cache"):
def decorator(func):
@wraps(func)
async def wrapper(*args, **kwargs):
key = f"{prefix}:{func.__name__}:{args}:{kwargs}"
cached = await r.get(key)
if cached:
return json.loads(cached)
result = await func(*args, **kwargs)
await r.setex(key, ttl, json.dumps(result))
return result
return wrapper
return decorator

@redis_cache(ttl=600)
async def get_popular_items(category: str) -> list[dict]:
return await db.fetch_popular(category)

常见面试问题

Q1: lru_cache 的局限?

答案

  1. 参数必须可哈希:不能缓存以 list/dict 为参数的函数
  2. 进程内存:多进程不共享,重启丢失
  3. 无 TTL:缓存永不过期(除非手动 cache_clear()
  4. 不能缓存异步函数:需用 aiocache 或自行封装

Q2: 缓存穿透/击穿/雪崩怎么处理?

答案

详细方案参考数据库系列 - 缓存问题

  • 穿透:查询不存在的 key → 缓存空值 / 布隆过滤器
  • 击穿:热点 key 过期 → 互斥锁 / 永不过期
  • 雪崩:大量 key 同时过期 → 随机 TTL 偏移

Q3: 什么时候用内存缓存、什么时候用 Redis?

答案

场景方案
纯 CPU 计算结果lru_cache
单进程热数据cachetools.TTLCache
多进程/多服务共享Redis
大规模分布式缓存Redis Cluster

相关链接