Fastapi教程:使用aioredis异步访问redis

本文将介绍如何使用 FastAPI 异步访问 Redis,包括环境配置、连接创建、数据库初始化、增删查改操作、键过期、管道(pipeline)操作以及事务管理等内容。

环境准备

首先,我们需要安装必要的依赖包。Redis 是一个键值存储系统,而 aioredis 是一个支持异步访问 Redis 的 Python 客户端库。你可以使用以下命令安装 FastAPI、Uvicorn 和 aioredis:

bash 复制代码
pip install fastapi
pip install uvicorn
pip install aioredis

在安装完成后,我们就可以开始编写代码了。

1. 配置 Redis 连接

首先,确保你已经安装并启动了 Redis 服务。可以通过以下命令启动 Redis:

bash 复制代码
redis-server

然后,我们创建一个 Redis 连接。为了支持异步操作,我们使用 aioredis 包。

python 复制代码
import aioredis

# 配置 Redis 连接
REDIS_URL = "redis://localhost:6379"

# 创建 Redis 连接
async def get_redis_connection():
    redis = await aioredis.from_url(REDIS_URL, encoding="utf-8", decode_responses=True)
    return redis

我们通过 aioredis.from_url 方法创建了一个 Redis 连接,它允许我们直接从指定的 Redis 服务 URL 中连接 Redis 服务器,并且设置编码和解码格式为 UTF-8,以便处理字符串数据。

2. FastAPI 实例化和数据库初始化

在 FastAPI 中,我们使用 Depends 依赖注入机制来获取 Redis 连接。通过 on_startup 事件,我们可以在 FastAPI 启动时进行一些初始化操作,如测试 Redis 连接。

python 复制代码
from fastapi import FastAPI, Depends

app = FastAPI()

# 获取 Redis 连接
async def get_db():
    redis = await get_redis_connection()
    try:
        yield redis
    finally:
        await redis.close()

# 在应用启动时初始化 Redis 连接
@app.on_event("startup")
async def on_startup():
    redis = await get_redis_connection()
    print("Redis connection initialized")
    await redis.close()

3. 数据库的增删查改操作(CRUD)

我们现在将实现一些常见的 Redis 操作,如增、删、查、改。

创建/设置数据

我们使用 Redis 的 set 命令来设置键值对。为了简化操作,我们将设置数据的函数定义为一个 POST 请求:

python 复制代码
from fastapi import HTTPException

@app.post("/set/{key}/{value}")
async def set_key(key: str, value: str, redis: aioredis.Redis = Depends(get_db)):
    try:
        await redis.set(key, value)  # 设置键值对
        return {"message": "Key set successfully"}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))
  • await redis.set(key, value):在 Redis 中设置键值对。

获取数据

我们使用 Redis 的 get 命令来获取数据。通过 GET 请求来查询某个键的值:

python 复制代码
@app.get("/get/{key}")
async def get_key(key: str, redis: aioredis.Redis = Depends(get_db)):
    value = await redis.get(key)  # 获取键对应的值
    if value is None:
        raise HTTPException(status_code=404, detail="Key not found")
    return {"key": key, "value": value}
  • await redis.get(key):获取指定键的值,如果键不存在,则返回 None

更新数据

Redis 是一个键值存储系统,我们可以通过 set 命令更新已经存在的键值对。如果键存在,值将被更新;如果不存在,则会创建新的键值对。

python 复制代码
@app.put("/update/{key}/{value}")
async def update_key(key: str, value: str, redis: aioredis.Redis = Depends(get_db)):
    exists = await redis.exists(key)
    if not exists:
        raise HTTPException(status_code=404, detail="Key not found")
    
    await redis.set(key, value)  # 更新键值对
    return {"message": "Key updated successfully"}
  • await redis.exists(key):检查键是否存在。

删除数据

我们使用 Redis 的 delete 命令删除指定的键:

python 复制代码
@app.delete("/delete/{key}")
async def delete_key(key: str, redis: aioredis.Redis = Depends(get_db)):
    result = await redis.delete(key)  # 删除指定键
    if result == 0:
        raise HTTPException(status_code=404, detail="Key not found")
    return {"message": "Key deleted successfully"}
  • await redis.delete(key):删除指定的键,返回删除的键数量。

4. 设置键的过期时间

Redis 提供了 expire 命令来设置键的过期时间。通过 EX 参数,我们可以设置键的过期时间为秒数,或者通过 PX 设置毫秒。

python 复制代码
@app.post("/set_with_expiration/{key}/{value}/{expiration}")
async def set_key_with_expiration(key: str, value: str, expiration: int, redis: aioredis.Redis = Depends(get_db)):
    await redis.set(key, value, ex=expiration)  # 设置过期时间
    return {"message": f"Key will expire in {expiration} seconds"}
  • ex=expiration:设置键的过期时间为 expiration 秒。

5. 使用管道(Pipeline)

Redis 提供了管道(Pipeline)功能,可以将多个命令打包成一个批量请求发送,提高性能。以下是一个使用管道操作多个键值的示例:

python 复制代码
@app.post("/set_multiple/{key}/{value}")
async def set_multiple_keys(key: str, value: str, redis: aioredis.Redis = Depends(get_db)):
    async with redis.pipeline() as pipe:
        for i in range(1, 6):
            await pipe.set(f"{key}_{i}", f"{value}_{i}")
        await pipe.execute()  # 执行管道中的所有命令
    return {"message": "Multiple keys set successfully"}
  • async with redis.pipeline():创建一个 Redis 管道。
  • await pipe.set(f"{key}_{i}", f"{value}_{i}"):向管道中添加多个设置命令。
  • await pipe.execute():执行管道中的所有命令。

6. Redis 事务管理

Redis 本身支持事务机制。通过管道,我们可以执行事务。管道可以保证所有命令一起执行,要么全部成功,要么全部失败。

python 复制代码
@app.post("/transaction/{key}/{value}")
async def redis_transaction(key: str, value: str, redis: aioredis.Redis = Depends(get_db)):
    async with redis.pipeline() as pipe:
        await pipe.set(key, value)
        await pipe.expire(key, 60)  # 设置过期时间为60秒
        await pipe.execute()  # 执行所有命令
    return {"message": "Transaction executed successfully"}
  • async with redis.pipeline():开始一个事务。
  • await pipe.set(key, value):设置键值对。
  • await pipe.expire(key, 60):设置键的过期时间。
  • await pipe.execute():执行事务。

完整代码示例

python 复制代码
from fastapi import FastAPI, HTTPException, Depends
import aioredis

app = FastAPI()

REDIS_URL = "redis://localhost:6379"

# 获取 Redis 连接
async def get_db():
    redis = await aioredis.from_url(REDIS_URL, encoding="utf-8", decode_responses=True)
    try:
        yield redis
    finally:
        await redis.close()

# 初始化 Redis 连接
@app.on_event("startup")
async def on_startup():
    redis = await get_db()
    print("Redis connection initialized")
    await redis.close()

# 设置数据
@app.post("/set/{key}/{value}")
async def set_key(key: str, value: str, redis: aioredis.Redis = Depends(get_db)):
    await redis.set(key, value)
    return {"message": "Key set successfully"}

# 获取数据
@app.get("/get/{key}")
async def get_key(key: str, redis: aioredis.Redis = Depends(get_db)):
    value = await redis.get(key)
    if value is None:
        raise HTTPException(status_code=404, detail="Key not found")
    return {"key": key, "value": value}

# 更新数据
@app.put("/update/{key}/{value}")
async def update_key(key: str, value: str, redis: aioredis.Redis = Depends(get_db)):
    exists = await redis.exists(key)
    if not exists:
        raise HTTPException(status_code=404, detail="Key not found")
    
    await redis.set(key, value)
    return {"message": "Key updated successfully"}

# 删除数据
@app.delete("/delete/{key}")
async def delete_key(key: str, redis: aioredis.Redis = Depends(get_db)):
    result = await redis.delete(key)
    if result == 0:
        raise HTTPException(status_code=404, detail="Key not found")
    return {"message": "Key deleted successfully"}

# 设置过期时间
@app.post("/set_with_expiration/{key}/{value}/{expiration}")
async def set_key_with_expiration(key: str, value: str, expiration: int, redis: aioredis.Redis = Depends(get_db)):
    await redis.set(key, value, ex=expiration)
    return {"message": f"Key will expire in {expiration} seconds"}

# 使用管道操作
@app.post("/set_multiple/{key}/{value}")
async def set_multiple_keys(key: str, value: str, redis: aioredis.Redis = Depends(get_db)):
    async with redis.pipeline() as pipe:
        for i in range(1, 6):
            await pipe.set(f"{key}_{i}", f"{value}_{i}")
        await pipe.execute()
    return {"message": "Multiple keys set successfully"}

# Redis 事务
@app.post("/transaction/{key}/{value}")
async def redis_transaction(key: str, value: str, redis: aioredis.Redis = Depends(get_db)):
    async with redis.pipeline() as pipe:
        await pipe.set(key, value)
        await pipe.expire(key, 60)
        await pipe.execute()
    return {"message": "Transaction executed successfully"}

总结

本文详细介绍了如何在 FastAPI 中使用异步方式访问 Redis,包括 Redis 连接的创建、数据的增删查改、键过期、使用管道操作和事务管理等内容。通过使用 aioredis 库,结合 FastAPI 提供的异步支持,可以高效地处理缓存数据,提升系统性能。希望本文对你在项目中使用 Redis 提供了帮助。

相关推荐
一个略懂代码的程序员28 分钟前
Redis01
java·redis
东阳马生架构1 小时前
Redis原理—5.性能和使用总结
redis
m_merlon1 小时前
Fastapi教程:使用 aioredis 连接池执行Redis 的高效异步操作
redis·fastapi
weisian1513 小时前
Redis篇-5--原理篇4--Lua脚本
数据库·redis·lua
荼蘼_4 小时前
宝塔内设置redis后,项目以及RedisDesktopManager客户端连接不上!
数据库·redis·缓存
Smile丶凉轩8 小时前
Redis的缓存
数据库·redis·缓存
weisian15118 小时前
Redis篇-4--原理篇3--Redis发布/订阅(Pub/Sub)
数据库·redis·缓存
新的算法1 天前
Redis数据库技术--数据结构
数据结构·数据库·redis
东阳马生架构1 天前
Redis原理—4.核心原理摘要
redis