aioredis v2.0 现在是 的完全兼容的 异步原生 实现 redis-py 。 重新编写了整个核心和公共 API 以遵循 redis-py 的实现 尽可能接近。 这意味着连接有一些重大变化 接口,但我们现在有一个在两者之间完全一致的接口 库,因此从 移植 redis-py 到 aioredis 应该(理论上)像 更改一些导入并添加 await在需要的地方声明。

Motivations ¶ 

截至 2019 年 12 月,该图书馆已被废弃。 代码变得陈旧,问题 堆积如山,我们很快就过时了 Redis 自己的功能集。 有鉴于此,做出决定以确保支持支持的障碍 潜在的维护者或贡献者将被最小化。 一个运行端口 redis-py 的 实现这一点。

此外,拥抱 redis-py 作为事实上的实现降低了障碍 新采用者的入门,因为界面现在几乎相同。

连接到Redis ¶ 

不再通过调用连接到redis await aioredis.create_pool(...). 相反,默认的初始化模式与 相同 redis-py :

 
import asyncio

import aioredis


async def main():
    # Redis client bound to single connection (no auto reconnection).
    redis = aioredis.from_url(
        "redis://localhost", encoding="utf-8", decode_responses=True
    )
    async with redis.client() as conn:
        await conn.set("my-key", "value")
        val = await conn.get("my-key")
    print(val)


async def redis_pool():
    # Redis client bound to pool of connections (auto-reconnecting).
    redis = aioredis.from_url(
        "redis://localhost", encoding="utf-8", decode_responses=True
    )
    await redis.set("my-key", "value")
    val = await redis.get("my-key")
    print(val)


if __name__ == "__main__":
    asyncio.run(main())
    asyncio.run(redis_pool())

如您所见, from_url(...)方法不是协程函数。 这是因为 连接是惰性创建的,而不是预先填充的,与模式保持一致 在 建立 redis-py 中 。 如果您需要立即建立连接,您可以 可以使用 aioredis.Redis.ping获取连接并ping您的redis实例。

管道和事务 (Multi/Exec) ¶ 

在之前的实现中,Pipeline 本质上是对 asyncio.gather. 设置到流水线的每个命令都立即推送到 Redis 它自己的任务。

这有一些令人惊讶的副作用:

  1. aioredis 管道比 慢得多 redis-py 管道 。
  2. 一个命令中的异常不一定会停止流水线的执行。
  3. 我们没有充分利用 Redis 的 Multi/Bulk 协议。
  4. 我们可能会同时使用过多的单个命令使 Redis 过载。

aioredis.Pipeline现在完全符合原来的 redis-py 执行:

 
import asyncio

import aioredis


async def main():
    redis = await aioredis.from_url("redis://localhost")
    async with redis.pipeline(transaction=True) as pipe:
        ok1, ok2 = await (pipe.set("key1", "value1").set("key2", "value2").execute())
    assert ok1
    assert ok2


asyncio.run(main())
 
import asyncio

import aioredis


async def main():
    redis = aioredis.from_url("redis://localhost")
    await redis.delete("foo", "bar")
    async with redis.pipeline(transaction=True) as pipe:
        res = await pipe.incr("foo").incr("bar").execute()
    print(res)


if __name__ == "__main__":
    asyncio.run(main())

清理 ¶ 

你可能已经注意到在上面的例子中我们没有明确地关闭我们的 主函数退出时的连接。 这是因为,再次像 redis-py 一样 ,我们的 客户端和连接已经实现 __del__方法,因此将尝试 垃圾收集时自动清理任何打开的连接。

但是,如果您发现需要自己管理连接生命周期,则可以 这样做:

 
import asyncio
import aioredis


async def main():
    pool = aioredis.ConnectionPool.from_url(
        "redis://localhost", decode_responses=True
    )
    meanings = aioredis.Redis(connection_pool=pool)
    try:
        await meanings.set("life", 42)
        print(f"The answer: {await meanings.get('life')}")
    finally:
        await pool.disconnect()


if __name__ == "__main__":
    asyncio.run(main())

最新消息 ¶ 

aioredis 现在 完全兼容 Redis 6.0,包括:

  1. ACL/RBAC
  2. 完整的 PubSub 支持 (2.8.0)

其中一些功能已部分实施或实施时存在许多已知问题, 但现在被认为是稳定的。

发生了什么 ¶ 

我们不再提供 Channel对 PubSub 的抽象。 这个实现是 马车,不太了解。 此外,我们的源代码中没有这样的抽象 实现( redis-py )。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐