FastAPI 中的缓存:解锁高性能开发
在当今数字化的世界中,所有操作——无论是滑动约会应用还是完成购买——都依赖于在后台高效工作的API。作为后端开发者,我们知道每毫秒都至关重要。那么,我们如何让API的响应速度更快呢?答案在于缓存。
一. 缓存的基本概念
缓存是一种将经常访问的数据存储在内存中的技术,这样API就可以立即响应,而不是每次都查询较慢的数据库。可以将其比作将关键调料(盐、胡椒、油)放在厨房台面上,而不是每次做饭时都去储藏室取。这节省了时间,使过程更加高效。同样,缓存通过将常请求的数据存储在快速、可访问的位置(如Redis)来减少API的响应时间。
二. 所需库的安装
要与Redis缓存连接FastAPI,我们需要预先安装以下库:
pip install fastapi uvicorn aiocache pydantic
-
Pydantic
用于创建数据库表和结构。 -
aiocache
用于在缓存上执行异步操作。 -
uvicorn
负责运行服务器。
三. Redis的设置与验证
在Windows系统中直接安装Redis目前是不可能的,因此需要在Windows子系统Linux (WSL) 中进行设置。以下是安装WSL的指令:
-
安装WSL | Microsoft Learn
通过以下命令在你的Windows机器上安装WSL:
wsl --install
安装完WSL后,使用以下命令安装Redis:
sudo apt update
sudo apt install redis-server
sudo systemctl start redis
要测试Redis服务器的连接性,可以使用以下命令:
redis-cli
执行后进入6379端口的虚拟终端,在此终端中可以输入Redis命令进行测试。
四. 设置FastAPI应用
接下来,我们创建一个简单的FastAPI应用,该应用检索用户信息并将其缓存以供未来请求使用。我们将使用Redis来存储缓存的响应。
1. 定义用户数据的Pydantic模型
使用Pydantic定义我们的用户模型,表示API响应的结构。
from pydantic import BaseModel
class User(BaseModel):
id: int # 用户ID
name: str # 用户姓名
email: str # 用户邮箱
age: int # 用户年龄
2. 创建缓存装饰器
为了避免为每个端点重复缓存逻辑,我们使用aiocache
库创建一个可重用的缓存装饰器。该装饰器将尝试从Redis中检索响应,然后再调用实际函数。
import json
from functools import wraps
from aiocache import Cache
from fastapi import HTTPException
def cache_response(ttl: int = 60, namespace: str = "main"):
"""
FastAPI端点的缓存装饰器。
ttl: 缓存的生存时间(秒)。
namespace: Redis中缓存键的命名空间。
"""
def decorator(func):
@wraps(func)
async def wrapper(*args, **kwargs):
user_id = kwargs.get('user_id') or args[0] # 假设用户ID是第一个参数
cache_key = f"{namespace}:user:{user_id}"
cache = Cache.REDIS(endpoint="localhost", port=6379, namespace=namespace)
# 尝试从缓存中检索数据
cached_value = await cache.get(cache_key)
if cached_value:
return json.loads(cached_value) # 返回缓存的数据
# 如果没有命中缓存,调用实际函数
response = await func(*args, **kwargs)
try:
# 将响应存储在Redis中,并设置生存时间
await cache.set(cache_key, json.dumps(response), ttl=ttl)
except Exception as e:
raise HTTPException(status_code=500, detail=f"缓存数据时出错: {e}")
return response
return wrapper
return decorator
3. 实现用户详细信息的FastAPI路由
现在,我们将实现一个FastAPI路由,根据用户ID检索用户信息。响应将使用Redis进行缓存,以便后续请求能够更快地访问。
from fastapi import FastAPI
app = FastAPI()
# 模拟数据库中的用户数据
users_db = {
1: {"id": 1, "name": "Alice", "email": "alice@example.com", "age": 25},
2: {"id": 2, "name": "Bob", "email": "bob@example.com", "age": 30},
3: {"id": 3, "name": "Charlie", "email": "charlie@example.com", "age": 22},
}
@app.get("/users/{user_id}")
@cache_response(ttl=120, namespace="users")
async def get_user_details(user_id: int):
# 模拟从用户数据库中检索数据
user = users_db.get(user_id)
if not user:
raise HTTPException(status_code=404, detail="用户未找到")
return user
4. 运行应用程序
通过以下命令启动FastAPI应用:
uvicorn main:app --reload
现在,你可以通过以下链接测试API以获取用户详细信息:
http://127.0.0.1:8000/users/1
第一次请求将从users_db
中获取数据,而后续请求将从Redis中检索数据。
五. 测试缓存
你可以通过检查存储在Redis中的键来验证缓存。打开Redis CLI:
redis-cli
使用以下命令查看所有存储的键:
KEYS *
这将显示所有在TTL期间存储的键。
六. 缓存在此示例中的工作原理
第一次请求
当用户数据第一次请求时,API从数据库(users_db
)中获取数据,并将结果存储在Redis中,设置生存时间为120秒。
后续请求
在TTL期间,任何对相同用户的后续请求都将直接从Redis中服务,从而加快响应速度并减少数据库的负载。
TTL(生存时间)
在120秒后,缓存条目过期,下次请求时将从数据库中重新获取数据,从而刷新缓存。
七. 结论
在本教程中,我们演示了如何在FastAPI应用中实现Redis缓存,通过一个简单的用户详细信息示例。通过缓存API响应,你可以显著提高应用程序的性能,特别是对于那些不频繁更改的数据。