FastAPI 中的缓存:解锁高性能开发

发布:2024-10-18 10:14 阅读:28 点赞:0

在当今数字化的世界中,所有操作——无论是滑动约会应用还是完成购买——都依赖于在后台高效工作的API。作为后端开发者,我们知道每毫秒都至关重要。那么,我们如何让API的响应速度更快呢?答案在于缓存

一. 缓存的基本概念

缓存是一种将经常访问的数据存储在内存中的技术,这样API就可以立即响应,而不是每次都查询较慢的数据库。可以将其比作将关键调料(盐、胡椒、油)放在厨房台面上,而不是每次做饭时都去储藏室取。这节省了时间,使过程更加高效。同样,缓存通过将常请求的数据存储在快速、可访问的位置(如Redis)来减少API的响应时间。

二. 所需库的安装

要与Redis缓存连接FastAPI,我们需要预先安装以下库:

pip install fastapi uvicorn aiocache pydantic
  • Pydantic用于创建数据库表和结构。
  • aiocache用于在缓存上执行异步操作。
  • uvicorn负责运行服务器。

三. Redis的设置与验证

在Windows系统中直接安装Redis目前是不可能的,因此需要在Windows子系统Linux (WSL) 中进行设置。以下是安装WSL的指令:

通过以下命令在你的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响应,你可以显著提高应用程序的性能,特别是对于那些不频繁更改的数据。