aioredis 的维护状态变化让不少项目面临升级选择,但它的能力并没有消失,而是被合并进 redis-py 的异步子模块 redis.asyncio 中。迁移的核心不是重写业务逻辑,而是调整客户端构造和资源释放方式。下面先给出三种客户端的定位对比,帮助理解过渡路径。

一、redis-py、aioredis 与 redis.asyncio 的定位与关系
redis-py 是最早的 Python Redis 客户端,提供同步阻塞接口,适用于 Django、Celery 等传统同步框架。aioredis 诞生于异步 IO 普及之前,为 asyncio 生态提供独立的 Redis 访问能力。后来 redis-py 4.2 引入 redis.asyncio 子模块,aioredis 2.0 则改为依赖 redis-py 并作为异步适配层发布,最终官方停止 aioredis 的新功能开发,推荐统一使用 redis.asyncio。三者的关系可以理解为:aioredis 是现代异步需求的过渡方案,redis.asyncio 是官方长期维护的异步接口。
对于一个正在使用 FastAPI 或 aiohttp 的项目,同步 redis-py 会在执行网络请求时阻塞事件循环,导致并发能力急剧下降。aioredis 解决了这一问题,但多维护一套库带来了版本兼容和 API 差异问题。官方合并后,异步能力成为 redis-py 的一部分,项目只需安装一个依赖即可同时拥有同步和异步客户端。下面这段代码展示了三种客户端的基础创建方式:
import redis # 同步客户端
import aioredis # 旧异步客户端(2.x 版本)
import redis.asyncio as async_redis # 新官方异步客户端
# 同步 redis-py
sync_client = redis.Redis(host='127.0.0.1', port=6379, decode_responses=True)
# 旧 aioredis 2.x 推荐写法
legacy_async_client = aioredis.from_url('redis://127.0.0.1:6379', decode_responses=True)
# 新 redis.asyncio 写法
new_async_client = async_redis.from_url('redis://127.0.0.1:6379', decode_responses=True)
从这段代码可以看到,aioredis 2.x 已经非常接近 redis.asyncio,迁移成本远低于从 aioredis 1.x 升级。如果你的项目仍在使用 aioredis 1.x 的 create_redis_pool 风格,则需要额外调整连接池创建和关闭逻辑,下一节会详细说明。
二、从 aioredis 迁移到 redis.asyncio 的具体路径
如果项目使用 aioredis 2.x,迁移非常直接,通常只需要修改 import 和少量资源关闭代码。第一步是替换导入语句,将 import aioredis 改为 import redis.asyncio as aioredis,这样大多数业务调用可以保持不变。对于基于 aioredis.from_url 创建的客户端,改写后即可正常运行,因为 aioredis 2.x 本身就转发到 redis-py 的异步实现。
# 迁移前:aioredis 2.x
import aioredis
client = aioredis.from_url('redis://127.0.0.1:6379', decode_responses=True)
# 迁移后:redis.asyncio
import redis.asyncio as aioredis
client = aioredis.from_url('redis://127.0.0.1:6379', decode_responses=True)
如果项目来自 aioredis 1.x,则连接池创建方式需要改动。create_redis_pool 会同时创建连接池和客户端,而 redis.asyncio 推荐显式创建 ConnectionPool 再传递给 Redis。同时参数名也从 minsize、maxsize 变为 max_connections。迁移前后对比如下:
# aioredis 1.x 旧写法
redis = await aioredis.create_redis_pool('redis://127.0.0.1:6379', minsize=5, maxsize=20)
# redis.asyncio 新写法
import redis.asyncio as redis
pool = redis.ConnectionPool.from_url('redis://127.0.0.1:6379', max_connections=20)
client = redis.Redis(connection_pool=pool)
资源关闭同样需要调整。aioredis 1.x 通常先调用 redis.close(),再执行 await redis.wait_closed()。aioredis 2.x 可以直接 await redis.close(),但官方更推荐在 redis.asyncio 中使用 await client.aclose(),因为它会同时关闭连接和连接池,避免遗漏。示例如下:
# 旧 aioredis 1.x redis.close() await redis.wait_closed() # 新 redis.asyncio 推荐方式 await client.aclose()
经过这三步修改,绝大部分基于字符串命令的 Redis 操作都不需要额外改动。迁移完成后可以通过全局搜索 aioredis 字样确认是否还有遗漏的导入或调用。
三、同步 redis-py 与异步 redis.asyncio 的接口差异及选择
同步与异步客户端的基础命令名称完全一致,区别在于异步客户端的方法返回协程,必须使用 await 获取结果。下面这段对比代码可以直观看出差异:
# 同步 redis-py
client.set('key', 'value')
value = client.get('key')
# 异步 redis.asyncio
await client.set('key', 'value')
value = await client.get('key')
redis.asyncio 还支持异步上下文管理器,可以在代码块结束时自动关闭连接,避免手动调用 aclose。同步 redis-py 则通常使用 with 语法或让连接池常驻。异步上下文管理器的用法如下:
import redis.asyncio as redis
async def main():
async with redis.Redis(host='127.0.0.1', port=6379) as client:
await client.set('status', 'ok')
print(await client.get('status'))
选择同步还是异步客户端,主要取决于运行环境。FastAPI、aiohttp、Telegram Bot 等 asyncio 框架应使用 redis.asyncio,以保证事件循环不被阻塞。Django、Flask、Scrapy、Celery 的同步任务可以继续使用 redis-py。需要特别注意的是,不要把同步 redis-py 直接放在异步协程中频繁调用,因为每次网络操作都会阻塞整个事件循环,导致 Web 服务响应变慢。一个项目里也可以同时使用两种客户端,但最好在命名上明确区分,例如 sync_redis 和 async_redis。
连接池配置同样要区分场景。异步客户端在高并发下若 max_connections 设置过小,会出现连接等待甚至 TimeoutError;同步客户端在多线程环境下也应使用 redis.ConnectionPool,不要为每个线程单独创建新连接。合理地复用连接池是迁移后性能稳定的关键。
四、迁移过程常见问题与排查
最常见的问题是导入错误。许多旧项目直接写 from aioredis import Redis,迁移到 redis.asyncio 后会报 ImportError,正确写法是 from redis.asyncio import Redis。同样,使用 aioredis.Redis 的地方也要全部替换为 redis.asyncio.Redis。建议迁移前先全局搜索所有 aioredis 的引用,避免运行时才暴露问题。
另一个容易出错的是 URL 配置。使用 TLS 连接时,aioredis 支持 rediss:// 协议,redis.asyncio.from_url 同样支持,但需要注意证书验证参数。例如自签名证书环境需要传入 ssl_cert_reqs 相关参数,否则会握手失败。示例代码如下:
import redis.asyncio as redis
client = redis.from_url(
'rediss://127.0.0.1:6380/0',
decode_responses=True,
ssl_cert_reqs=None
)
连接池耗尽也是迁移后常见的问题之一。异步客户端的事件循环调度下,如果 max_connections 设置过小,多个协程会排队等待可用连接,最终可能触发超时。排查时可以先用 await client.ping() 简单检测连接是否正常,再结合业务并发量调整连接池大小。还要避免在每个请求处理函数中新建 Redis 客户端,应该用全局单例或依赖注入方式复用同一个客户端或连接池。
如果项目规模较大,可以采用渐进式迁移:先在一个小模块中替换 aioredis,通过测试后再逐步覆盖其他模块。过渡期间可以保留 aioredis 依赖,直到所有调用都切换到 redis.asyncio 再将其移除。完成迁移后建议清理不再需要的旧连接池参数和关闭逻辑,保持代码整洁。
redis-pyaioredisredis.asyncio修改时间:2026-08-23 03:41:53