
redis-py 连接指南从单节点、Sentinel、Cluster 到异步客户端的完整连接体系【免费下载链接】redis-pyRedis Python client项目地址: https://gitcode.com/GitHub_Trending/re/redis-py本篇指南以 redis-pyRedis Python client官方文档 docs/connections.rst 为骨架系统讲解该库提供的全系列连接客户端直接连接标准 Redis 节点的通用客户端Generic Client、面向高可用的 Sentinel 客户端、面向分片集群的 Cluster 客户端以及对应的异步asyncio版本并深入Connection与ConnectionPool的底层实现。读完本文你将掌握不同部署形态下 redis-py 客户端的选择依据、构造参数含义、URL 配置方式与连接池复用技巧并能依据源码理解各客户端的连接管理原理。客户端选型总览redis-py 针对不同的 Redis 部署拓扑提供了四类连接入口全部集中在 redis/client.py、redis/sentinel.py、redis/cluster.py 与 redis/asyncio/ 目录下部署形态同步客户端异步客户端核心类位置单节点 / 主从redis.Redisredis.asyncio.client.Redisredis/client.py、redis/asyncio/client.pySentinel 高可用redis.sentinel.Sentinelredis.asyncio.sentinel.Sentinelredis/sentinel.py、redis/asyncio/sentinel.pyCluster 集群redis.cluster.RedisClusterredis.asyncio.cluster.RedisClusterredis/cluster.py、redis/asyncio/cluster.py底层连接 / 连接池redis.connection.Connection/ConnectionPoolredis.asyncio.connection.Connection/ConnectionPoolredis/connection.py、redis/asyncio/connection.py同步与异步两个体系共享相同的命令集与参数语义区别仅在于异步客户端的方法返回awaitable对象。下文逐类展开。通用客户端Generic Client通用客户端redis.Redis用于直接连接一个标准 Redis 节点是 redis-py 最基础、最常用的入口。其类定义位于 redis/client.py继承自RedisModuleCommands、CoreCommands、SentinelCommands因此同时具备 Redis 核心命令、模块命令与 Sentinel 管理命令的调用能力。直接构造方式最直观的用法是传入主机与端口import redis r redis.Redis(hostlocalhost, port6379) r.set(foo, bar) print(r.get(foo)) # bbarRedis.__init__见 redis/client.py支持一组丰富的连接参数常用参数及其默认值如下参数默认值说明host/portlocalhost/6379目标 Redis 节点地址db0逻辑数据库编号015由服务端databases配置决定上限username/passwordNone认证凭据Redis 6 支持 ACL 用户名socket_timeout默认超时读写超时秒None表示不超时socket_connect_timeout默认值建立 TCP 连接的超时秒socket_read_size默认值单次读取套接字的缓冲区大小字节socket_keepaliveTrue是否开启 TCP keepalive默认开启空闲 30 秒、间隔 5 秒、3 次探测可用socket_keepalive_options如{socket.TCP_KEEPIDLE: 30}定制decode_responsesFalse为True时将响应解码为 UTF-8 字符串而非字节串encoding/encoding_errorsutf-8/strict编解码配置max_connectionsNone连接池上限未指定时由连接池默认100决定single_connection_clientFalse为True时不使用连接池、独占单条连接此时客户端实例不是线程安全的health_check_interval0空闲连接健康检查间隔秒0表示禁用client_nameNone通过CLIENT SETNAME设置的客户端名称便于服务端排查ssl系列Falsessl_keyfile、ssl_certfile、ssl_ca_certs、ssl_check_hostname等 TLS 配置retry/retry_on_error默认指数退避重试网络错误重试策略详见 docs/retry.rst从源码可见redis/client.py当未显式传入connection_pool时客户端会根据unix_socket_path是否设置自动选择UnixDomainSocketConnection或 TCP 型Connection若sslTrue则选用SSLConnection并把上述参数统一交给连接池构造。因此这些连接参数本质上都会传递到Connection与ConnectionPool层。URL 方式from_urlRedis.from_url见 redis/client.py允许用连接串一次性配置客户端并自动完成连接池构建import redis # 支持三种 scheme r redis.Redis.from_url(redis://localhost:6379/0) # TCP r_ssl redis.Redis.from_url(rediss://user:passlocalhost:6379/0) # SSL 包装的 TCP r_unix redis.Redis.from_url(unix:///path/to/redis.sock?db0) # Unix 域套接字 # 可叠加关键字参数与查询串参数 r redis.Redis.from_url(redis://localhost:6379/0?decode_responsesTrue, max_connections50)数据库编号的解析优先级依次为URL 查询串中的db参数如redis://localhost?db0→ URL 路径如redis://localhost/0→from_url的关键字参数db均未指定时默认db0。查询串中的参数会被自动转换为合适的 Python 类型布尔值可写作True/False或Yes/No无法转换时抛出ValueError且查询串参数优先于关键字参数。所有 URL 值与用户名、密码均会经过urllib.parse.unquote进行百分号解码。从已有连接池构建from_pool若需精细控制连接池的生命周期可使用Redis.from_pool(connection_pool)redis/client.py。需要注意from_pool返回的客户端会接管ownership连接池在客户端关闭或被垃圾回收时关闭池内全部连接因此同一个池不要通过from_pool共享给多个客户端线程间交替关闭会中断对方正在使用的连接。若要共享一个池应直接使用Redis(connection_poolpool)构造不接管池的关闭并结合上下文管理器管理池from redis import Redis from redis.connection import ConnectionPool with ConnectionPool.from_url(redis://localhost:6379/0) as pool: r Redis(connection_poolpool) # 不接管池的生命周期可安全共享 r.set(foo, bar)Sentinel 客户端Redis Sentinel 为 Redis 提供高可用能力它持续监控主节点与副本节点在主节点故障时自动执行故障转移failover并选举新主节点。Sentinel 本身以独立进程运行默认端口 26379并提供一组只能在 Sentinel 模式下执行的专用命令因此需要专门的客户端来连接与操作 Sentinel 节点。Sentinel 模式下的完整部署说明见 docs/geographic_failover.rst本地开发可用仓库提供的 dockers/sentinel.conf 快速搭建哨兵环境。连接与发现Sentinel类Sentinel类redis/sentinel.py接收哨兵节点列表对每个节点内部封装一个Redis客户端。官方文档给出的连接示例假设 Sentinel 与 Redis 分别运行在下述端口 from redis import Sentinel sentinel Sentinel([(localhost, 26379)], socket_timeout0.1) sentinel.discover_master(mymaster) (127.0.0.1, 6379) sentinel.discover_slaves(mymaster) [(127.0.0.1, 6380)]其中sentinels哨兵节点列表每个节点是(hostname, port)二元组min_other_sentinels哨兵视为可信所需的最少对等哨兵数量。查询某个哨兵时若其报告的对等节点数低于该阈值其响应将不被采信见 redis/sentinel.py 与check_master_state中的num-other-sentinels校验sentinel_kwargs连接哨兵节点时使用的参数字典任何普通 Redis 连接参数均可放入未指定时自动继承connection_kwargs中以socket_开头的选项如socket_timeout、socket_keepalive见 redis/sentinel.pyforce_master_ip强制指定 master 地址的 IP可覆盖哨兵返回的ip用于 NAT 或容器场景见discover_master实现redis/sentinel.py。discover_master(service_name)会遍历哨兵节点调用SENTINEL MASTERS校验 master 状态必须是 master、未处于主观下线 sdown / 客观下线 odown、对等哨兵数量达标后返回(ip, port)找不到合格 master 时抛出MasterNotFoundErrorMasterNotFoundError与SlaveNotFoundError均定义于 redis/sentinel.py继承自ConnectionError。discover_slaves(service_name)则通过SENTINEL SLAVES查询并过滤掉处于 sdown/odown 状态的副本返回存活的副本地址列表。另外Sentinel实现了上下文管理器协议__enter__/__exit__并支持close()关闭全部内部哨兵客户端及其连接池见 redis/sentinel.py。读写分离master_for与slave_forSentinel的真正价值在于动态发现读写节点并自动跟随故障转移。master_for与slave_for以及语义更准确的别名replica_for分别返回绑定 master 或 slave 的Redis客户端默认redis_classRedis底层均使用SentinelConnectionPool连接池见 redis/sentinel.pyfrom redis.sentinel import Sentinel sentinel Sentinel([(localhost, 26379)], socket_timeout0.1) # 写客户端始终路由到当前 master发生故障转移后自动探测新 master master sentinel.master_for(mymaster, socket_timeout0.1) master.set(foo, bar) # 读客户端在存活副本之间轮询round-robin适合读多写少场景 slave sentinel.slave_for(mymaster, socket_timeout0.1) print(slave.get(foo)) # bbar从master_for/slave_for的源码实现可以看到二者只是分别向连接池注入is_masterTrue/False后再用redis_class.from_pool(...)包装连接池。因此master 客户端在故障转移后会通过哨兵重新发现新 master当检测到原 master 地址变化时连接池会断开所有空闲连接使后续请求自然切换到新地址见 redis/sentinel.pyslave 客户端通过rotate_slaves以随机起点 循环round-robin方式在存活副本间分配读请求全部副本不可用时回退到 master 地址仍失败才抛出SlaveNotFoundError见 redis/sentinel.py。SentinelConnectionPool 与 SentinelManagedConnectionSentinelConnectionPoolredis/sentinel.py继承自ConnectionPool是 Sentinel 客户端的连接池实现。其关键设计构造参数service_name服务名即哨兵监控的主从组名、sentinel_managerSentinel实例、is_master池面向 master 还是 slave默认True、check_connection连接建立后是否立即发送PING做健康检查默认False连接类自动选择传入sslTrue时使用SentinelManagedSSLConnection否则使用SentinelManagedConnection见 redis/sentinel.py地址解析全部委托给内部的SentinelConnectionPoolProxy其中get_master_address每次都会向哨兵重新询问 master 地址并缓存比对rotate_slaves实现副本轮询redis/sentinel.py。SentinelManagedConnectionredis/sentinel.py是 Sentinel 专用的连接类建立连接时按is_master决定连接到 master 或轮询到的 slave读取响应时若遇到ReadOnlyError会判断原 master 已被降级为 slave主动断开连接以便下次重连时重新向哨兵查询新 master见 redis/sentinel.py。这正是 Sentinel 客户端能够透明应对故障转移的底层机制。Cluster 客户端RedisCluster客户端用于连接 Redis Cluster集群分片模式。与单节点/Sentinel 模式不同集群的数据按哈希槽slot分布在各节点上客户端需要维护槽位与节点的映射关系并处理MOVED/ASK重定向。RedisCluster 与 ClusterNodefrom redis.cluster import RedisCluster, ClusterNode # 方式一给定一个启动节点 rc RedisCluster(hostlocalhost, port7000) # 方式二显式构造启动节点列表 node ClusterNode(localhost, 7000) rc RedisCluster(startup_nodes[node], require_full_coverageFalse) rc.set(foo, bar) print(rc.get(foo)) # bbarClusterNoderedis/cluster.py封装单个集群节点的地址信息host、port 及可选的 server_type 等startup_nodes是用于初始引导bootstrapping的节点列表——客户端会通过这些节点执行CLUSTER SLOTS获取完整的槽位拓扑。RedisCluster.__init__redis/cluster.py还支持以下常用参数参数默认值说明startup_nodes/host/portNone/localhost/6379引导节点二选一即可require_full_coverageTrue为True时要求所有槽位均被覆盖否则构造客户端即抛出RedisClusterException为False时允许部分槽位缺失但服务端若开启cluster-require-full-coverage yes相关命令仍可能报ClusterDownErrorreinitialize_steps5槽位拓扑重新初始化的触发阈值按命令执行次数计read_from_replicasFalse已弃用旧版从副本读开关建议改用load_balancing_strategyload_balancing_strategyNone从副本读的负载均衡策略如轮询数据为最终一致dynamic_startup_nodesTrue为True时把发现到的全部节点作为下次拓扑刷新的依据address_remapNone地址重映射回调用于 NAT/端口映射场景将CLUSTER SLOTS返回的地址转换为可访问地址retry默认重试对象集群错误如MOVED/ASK的重试策略集群客户端同样支持RedisCluster.from_urlredis/cluster.pyURL 语法与通用客户端一致。集群 Pipeline在集群上使用 Pipeline 时由于命令可能路由到不同节点客户端会将命令按槽位分组发送。同步实现为redis.cluster.ClusterPipelineredis/cluster.py核心方法为execute_command与executefrom redis.cluster import RedisCluster rc RedisCluster(hostlocalhost, port7000) with rc.pipeline(transactionFalse) as pipe: pipe.set(foo, bar) pipe.get(foo) result pipe.execute()异步客户端asyncioredis-py 从 4.2 版本起提供了完整的 asyncio 支持接口与同步版一一对应。异步通用客户端为redis.asyncio.client.Redisredis/asyncio/client.py用法import asyncio import redis.asyncio as redis async def main(): # 直接构造 r redis.Redis(hostlocalhost, port6379, decode_responsesTrue) # 或使用 URL r redis.from_url(redis://localhost:6379/0) await r.set(foo, bar) print(await r.get(foo)) # bar # 使用完毕后关闭内部连接池随之释放 await r.aclose() asyncio.run(main())异步客户端的所有命令方法均返回可等待对象必须用await调用连接池、重试、SSL、Sentinel 等参数语义与同步版完全一致。异步版Redis.from_url的实现同样构建一个ConnectionPool并设置auto_close_connection_pool见 redis/asyncio/client.py 起的类方法因此需要记住在结束时显式关闭客户端或在async with上下文管理器中自动释放。完整的异步示例可参考仓库中的 docs/examples/asyncio_examples.ipynb。异步 Cluster 客户端异步集群客户端redis.asyncio.cluster.RedisClusterredis/asyncio/cluster.py与同步版接口对齐import asyncio from redis.asyncio.cluster import RedisCluster, ClusterNode async def main(): rc RedisCluster(hostlocalhost, port7000) # 或 rc RedisCluster(startup_nodes[ClusterNode(localhost, 7000)]) await rc.set(foo, bar) print(await rc.get(foo)) await rc.aclose() asyncio.run(main())异步集群体系包含三个核心类均位于 redis/asyncio/cluster.pyRedisClusterL223异步集群客户端负责拓扑发现、槽位路由与命令分发ClusterNodeL1631异步版节点描述ClusterPipelineL2464异步集群 Pipeline核心公开方法同样为execute_command与executeasync def pipeline_demo(): rc RedisCluster(hostlocalhost, port7000) async with rc.pipeline(transactionFalse) as pipe: pipe.set(k1, v1) pipe.get(k1) results await pipe.execute() await rc.aclose()Connection 与 Connection Pool连接体系的底层基石Connection 类redis.connection.Connectionredis/connection.py负责与 Redis 服务器之间的 TCP 通信是所有上层客户端的地基。其构造参数包含host默认localhost、port默认6379、socket_keepalive默认开启 TCP keepalive并支持通过socket_keepalive_options定制如{socket.TCP_KEEPIDLE: 30}等选项等。底层_connect方法redis/connection.py模仿socket.create_connection的行为通过socket.getaddrinfo解析主机同时支持 IPv4/IPv6创建套接字后设置TCP_NODELAY按需开启SO_KEEPALIVE并应用 keepalive 选项先用socket_connect_timeout建立连接连接成功后切换为socket_timeout作为读写超时遍历getaddrinfo返回的全部地址尝试连接全部失败才抛出最后的OSError。redis.connection模块还提供SSLConnectionTLS 连接与UnixDomainSocketConnectionUnix 域套接字连接等变体ConnectionPool会根据配置自动选用。ConnectionPool 连接池ConnectionPoolredis/connection.py实现了连接的创建、复用与上限控制避免每条命令都新建 TCP 连接from redis.connection import ConnectionPool pool ConnectionPool( hostlocalhost, port6379, max_connections50, # 池上限默认 100超过后抛出 ConnectionError decode_responsesTrue, ) r redis.Redis(connection_poolpool) # 显式共享连接池连接池的关键行为max_connections默认值为100且必须是非负整数否则抛出ValueError见 redis/connection.py达到上限时get_connection会抛出ConnectionErrorconnection_class参数决定连接类型默认ConnectionTCP可换用UnixDomainSocketConnection或SSLConnectionConnectionPool.from_url与Redis.from_url共享同一套 URL 解析逻辑三种 scheme、db优先级、查询串类型转换与优先级规则完全一致见 redis/connection.py支持disconnect(inuse_connections...)断开空闲或全部连接以及get_connection_count()查看当前池内连接统计redis/connection.py额外支持maint_notifications_config仅 RESP3 下的维护通知、metadata_resolver客户端缓存命令资格判定、cache/cache_configRESP3 客户端缓存等高级能力。异步版redis.asyncio.connection.Connectionredis/asyncio/connection.py与ConnectionPoolredis/asyncio/connection.py提供相同的功能区别在于其底层使用 asyncio 的事件循环与异步套接字读写不阻塞事件循环。连接池的共享与所有权综合前面几节可以看到redis-py 对谁负责关闭连接池有明确约定Redis.from_url/Redis.from_pool客户端接管连接池客户端关闭/GC 时同步关闭池直接Redis(connection_poolpool)客户端不接管池池可被多个客户端安全共享由调用方管理生命周期推荐配合ConnectionPool的上下文管理器使用Sentinel的master_for/slave_for每个返回的客户端拥有独立的SentinelConnectionPool因此应长期持有并使用同一个客户端实例避免频繁创建导致池泛滥。小结与延伸阅读选择哪种连接客户端取决于你的 Redis 部署形态单节点或简单主从redis.Redis通用客户端即可哨兵高可用使用Sentinelmaster_for/slave_for获得自动故障转移与读写分离Cluster 集群使用RedisCluster客户端负责槽位路由与拓扑刷新高并发 IO 密集场景优先选用redis.asyncio异步版本需要精细控制连接生命周期直接操作ConnectionPool并遵循上述所有权约定。官方文档 docs/connections.rst 中通过autoclass指令自动生成了上述全部类的成员级 API 参考可作为精确查参手册仓库内的 docs/examples/connection_examples.ipynb 与 docs/examples/asyncio_examples.ipynb 提供了可运行的全量示例配合 tests/test_connect.py、tests/test_connection.py、tests/test_sentinel.py 等测试用例可以进一步验证各连接方式在实际环境中的行为。此外docs/connections.rst 提到的 Sentinel 高可用机制可结合 docs/geographic_failover.rst 与 docs/retry.rst重试策略一起阅读构建完整的生产级连接方案。【免费下载链接】redis-pyRedis Python client项目地址: https://gitcode.com/GitHub_Trending/re/redis-py创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考