最新版 redis-py 操作 redis(同步、异步、集群、连接池)

现在的 Python 异步操作 redis,有三种( aredis 、aioredis、asynio_redis) 但是都不推荐

背景

从 redis.py 4.2.0rc1+ 开始,Aioredis 已经集成到 redis-py 中,并且 Aioredis 将不再更新维护, 导入方式:from redis import asyncio as aioredis, 本次验证的是 redis==4.6.0

#!/usr/bin/env python
# -*- coding=utf8 -*-
# 从 redis.py  4.2.0rc1+ 开始,Aioredis 已经集成到 redis.py 中,并且 Aioredis 将不再更新维护,
# 导入:from redis import asyncio as aioredis (只有 2023 版本的 pycharm 才不会报错)

from redis import asyncio as aioredis  # noqa
import redis
from typing import Dict, Tuple, List

# 为了方便测试将配置写死置顶
host = '1.1.1.1'
port = 13310
password = 'guest'
db = 0


class RedisManager(object):
    _pool_dict: Dict[Tuple[str, int, int, str], redis.ConnectionPool] = {}

    def __init__(
            self,
            host: str = '127.0.0.1',
            port: int = 6379,
            db: int = 0,
            password: str = '',
            decode_responses: bool = True,
            max_connections: int = 50
    ) -> None:
        pool_key = (host, port, db, password)
        if pool_key not in self._pool_dict:
            self._pool_dict[pool_key] = redis.ConnectionPool(
                host=host,
                port=port,
                db=db,
                password=password,
                decode_responses=decode_responses,
                max_connections=max_connections
            )
        self._r = redis.Redis(connection_pool=self._pool_dict[pool_key])
        self._ping()

    def get_redis(self) -> redis.Redis:
        return self._r

    def _ping(self):
        try:
            self._r.ping()
        except BaseException as e:
            raise e


class RedisMixin(object):

    def __init__(
            self,
            host="localhost",
            port=6379,
            db=0,
            password=None,
            ssl=False,
    ):
        self.host = host
        self.port = port
        self.db = db
        self.password = password
        self.ssl = ssl

    @property
    def redis_db_frame(self) -> redis.Redis:
        # 获取单点连接
        return redis.Redis(host=self.host, port=self.port, password=self.password,
                           db=self.db, decode_responses=True)

    @property
    def redis_db_pool(self) -> redis.Redis:
        # 获取连接池
        return RedisManager(host=self.host, port=port, password=self.password,
                            db=self.db, decode_responses=True).get_redis()

    @property
    def redis_cluster_frame(self) -> redis.RedisCluster:
        # 获取 Cluster 连接
        return redis.RedisCluster(host=self.host, port=self.port, password=self.password,
                                  decode_responses=True, ssl=False)  # aws 需要 ssl=True


class AioRedisManager(object):
    _pool_dict: Dict[Tuple[str, int, int, str], redis.ConnectionPool] = {}

    def __init__(
            self,
            host: str = '127.0.0.1',
            port: int = 6379,
            db: int = 0,
            password: str = '',
            decode_responses: bool = True,
            max_connections: int = 50,
    ) -> None:
        pool_key = (host, port, db, password)
        if pool_key not in self._pool_dict:
            self._pool_dict[pool_key] = aioredis.ConnectionPool(
                host=host,
                port=port,
                db=db,
                password=password,
                decode_responses=decode_responses,
                max_connections=max_connections
            )
        self._r = aioredis.Redis(connection_pool=self._pool_dict[pool_key])
        asyncio.create_task(self._ping_async())

    async def get_redis(self) -> aioredis.Redis:
        return self._r

    async def _ping_async(self):
        try:
            await self._r.ping()
        except Exception as e:
            raise e


class AioRedisMixin(object):
    def __init__(
            self,
            host: str = '127.0.0.1',
            port: int = 6379,
            db: int = 0,
            password: str = '',
            decode_responses: bool = True,
            max_connections: int = 50,
            ssl=False,
    ):
        self.host = host
        self.port = port
        self.db = db
        self.password = password
        self.decode_responses = decode_responses
        self.max_connections = max_connections
        self.ssl = ssl

    @property
    async def redis_db_frame(self) -> aioredis.Redis:
        return aioredis.Redis(host=self.host, port=self.port, password=self.password,
                              db=self.db, decode_responses=self.decode_responses)

    @property
    async def redis_db_pool(self) -> aioredis.Redis:
        return await AioRedisManager(host=self.host, port=port, password=self.password,
                                     db=self.db, decode_responses=self.decode_responses).get_redis()

    @property
    async def redis_cluster_frame(self) -> aioredis.RedisCluster:
        return aioredis.RedisCluster(host=self.host, port=self.port, password=self.password,
                                     decode_responses=self.decode_responses, ssl=self.ssl)  # aws 需要 ssl=True


async def main():
    # 链接单点
    # pool = await aioredis.Redis(host=host, port=port, password=password, decode_responses=True, )
    # res = await pool.get('name')
    # print(res)

    # 集群连接 (集群)
    # redis_host = "172.17.120.83;172.17.120.84;172.17.120.85;172.17.120.86;172.17.120.87;172.17.120.88".split(';')
    # password = "123@2022"
    # 使用方法 1
    # for host in redis_host:
    #     async with aioredis.RedisCluster(host=host, port=6379, password=password, decode_responses=True, ) as conn:
    #         res = await conn.get('name')
    #         print(res)
    # 使用方法 2
    # for host in redis_host:
    #     conn = await aioredis.RedisCluster(host=host, port=6379, password=password, decode_responses=True, )
    #     res = await conn.get('name')
    #     print(res)
    #     # 关闭 RedisCluster 连接
    #     await conn.close()

    # pool 连接
    # pool = aioredis.ConnectionPool(
    #     host=host,
    #     port=port,
    #     db=db,
    #     password=password,
    #     decode_responses=True,
    #     max_connections=50
    # )
    # _r = aioredis.Redis(connection_pool=pool)
    # res = await _r.get('name')
    # print(res)

    # 封装一下
    # 链接单点
    r = AioRedisMixin(host=host, port=port, password=password, db=0)
    rc1 = await r.redis_db_frame
    res = await rc1.get('name')
    print(res)

    # pool 连接 redis_db_pool
    # rc1 = await AioRedisMixin(host=host, port=port, password=password, db=0).redis_db_pool
    # rc = AioRedisMixin(host=host, port=port, password=password, db=0)
    # rc1 = await rc.redis_db_pool
    # res = await rc1.get('name')
    # print(res)

    # 集群连接 (集群)
    # redis_host = "172.17.120.83;172.17.120.84;172.17.120.85;172.17.120.86;172.17.120.87;172.17.120.88".split(';')
    # password = "123@2022xx"
    # # 使用方法 1
    # for host in redis_host:
    #     rc = await AioRedisMixin(host=host, port=6379, password=password, db=0).redis_cluster_frame
    #     async with rc as conn:
    #         res = await conn.get('name')
    #         print(res)
    #     # 使用 pipeline
    #     async with rc as conn:
    #         pipe = conn.pipeline()
    #         for i in range(1, 20):
    #             pipe.get(f'name')
    #         res = await pipe.execute()
    #         print(res)
    # 使用方法 2
    # for host in redis_host:
    #     conn = await AioRedisMixin(host=host, port=6379, password=password).redis_cluster_frame
    #     res = await conn.get('name')
    #     print(res)
    #     # 关闭 RedisCluster 连接
    #     await conn.close()
    #
    #     # 使用 pipeline
    #     pipe = conn.pipeline()
    #     for i in range(1, 20):
    #         pipe.get(f'name')
    #     res = await pipe.execute()
    #     print(res)
    #     # 关闭 RedisCluster 连接
    #     await conn.close()


if __name__ == '__main__':
    import asyncio

    asyncio.run(main())

posted @ 2023-08-08 17:57  つつつつつつ  阅读(1110)  评论(0编辑  收藏  举报