最新版 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())