API服务里经常会遇到一个问题:
同一个数据被反复请求了很多次。
比如:
客户端A
↓
请求API
↓
第三方服务
客户端B
↓
请求API
↓
第三方服务
客户端C
↓
请求API
↓
第三方服务如果第三方数据变化不频繁,那这些请求其实存在大量重复。
这时候缓存就很有价值了。
什么是缓存
最简单的理解:
第一次请求
↓
拿数据
↓
存起来
第二次请求
↓
直接读缓存比如:
API
↓
Cache
↓
有数据 → 直接返回
↓
没数据
↓
请求真实数据源这样可以减少后端或者第三方的压力。
TTL是什么
TTL是:
Time To Live
也就是缓存能活多久。
比如:
TTL = 60秒意思是数据进缓存之后最多保存60秒。
60秒之后再重新去拿真实数据。
这对于一些变化不是特别频繁的数据很合适。
TTLCache
Python里可以用cachetools提供的TTLCache。
比如:
from cachetools import TTLCache
cache = TTLCache(
maxsize=1000,
ttl=60
)这里:
maxsize = 1000表示最多保存1000条缓存。
而:
ttl = 60表示缓存存活60秒。
在FastAPI里用
比如:
from fastapi import FastAPI
app = FastAPI()
cache = TTLCache(
maxsize=1000,
ttl=60
)接口:
@app.get("/data")
async def get_data():
if "data" in cache:
return cache["data"]
data = await fetch_data()
cache["data"] = data
return data这样第一次请求会去拿真实数据。
后面的请求直接读缓存。
缓存键很重要
如果API有参数:
/api/user?id=1
/api/user?id=2不能简单用:
cache["user"]不然不同用户的数据会互相覆盖。
更合理:
key = f"user:{user_id}"然后:
if key in cache:
return cache[key]这样:
user:1
user:2
user:3就是不同的缓存了。
缓存什么比较合适
我一般更倾向缓存:
第三方API
变化不频繁的数据
昂贵计算结果
公开数据
重复查询结果不太适合缓存:
强实时数据
高度个性化数据
权限敏感数据
必须保证最新的数据缓存的本质就是:
用一点数据新鲜度换性能。
缓存不是越久越好
比如:
天气
实时库存
实时余额可能只适合很短的TTL。
而:
网站公告
配置数据
学校课程信息可能几分钟甚至更久都能接受。
TTL应该根据业务来定。
内存缓存的局限
TTLCache很简单。
但它是:
进程内存缓存。
假如服务器:
Process A
Process B两个进程之间不共享同一个缓存。
如果服务重启 → 缓存全没了
所以TTLCache更适合:
单进程
小型API
简单服务
短生命周期缓存以后服务规模大了,就要考虑Redis之类的独立缓存服务。
缓存也要考虑异常
比如:
data = await fetch_data()
cache[key] = data如果真实数据源请求失败,就不该把错误结果也缓存进去。
应该保证:
请求成功
↓
写入缓存
请求失败
↓
返回错误
↓
不污染缓存如果业务允许,还可以进一步做:
缓存过期
↓
尝试刷新
↓
刷新失败
↓
用旧数据这就属于更复杂的缓存策略了。
我为什么喜欢TTLCache
它最大的优势不是功能强。
而是:
足够简单。
很多小型API服务根本不用急着上Redis。
如果需求只是:
"同一个接口60秒内别重复请求第三方API。"
那:
TTLCache(
maxsize=1000,
ttl=60
)已经够用了。
不用额外部署服务,也不用维护Redis。
总结
缓存不是"用了Redis才叫缓存"。
对很多个人项目和小型API来说:
FastAPI
+
TTLCache已经能解决大量重复请求的问题。
等到项目真的需要:
多进程共享
分布式
持久化
复杂缓存策略再考虑Redis也不迟。
工程设计里,我越来越倾向:
先用能解决当前问题的简单方案,别一开始就把架构搞得太复杂。