十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

redis-py 命令体系完全指南:CoreCommands、Sentinel 与 Redis Cluster 命令的架构与实战

redis-py 命令体系完全指南:CoreCommands、Sentinel 与 Redis Cluster 命令的架构与实战 redis-py 命令体系完全指南CoreCommands、Sentinel 与 Redis Cluster 命令的架构与实战【免费下载链接】redis-pyRedis Python client项目地址: https://gitcode.com/GitHub_Trending/re/redis-py导读本文以 docs/commands.rst 为骨架系统讲解 redis-py当前仓库GitHub_Trending/re/redis-py项目定位为 Redis Python client中全部 Redis 命令的暴露方式与使用范式标准单机客户端如何通过CoreCommands混入获得全套命令、Sentinel 客户端如何获得哨兵专属命令、Redis Cluster 客户端如何通过RedisClusterCommands获得集群命令并按哈希槽自动路由。读完本文你将掌握同步/异步两套命令 API 的完整调用链、set/get等核心命令的参数语义、Sentinel 与 Cluster 的接入方式以及从命令定义到协议执行再到响应解析的底层实现路径。一、命令文档的定位一份“命令门面”指南docs/commands.rst是 redis-py 官方文档中的命令索引页全文只做三件事用一段话说明文档中列出的函数用于复刻等价的 Redis 命令通常可以直接作为 redis 连接对象的方法来调用给出最简单的set/get示例通过 Sphinx 的autoclass指令把三类核心命令类CoreCommands、SentinelCommands、RedisClusterCommands的完整方法签名直接嵌入文档。因此这份文档的“正文”其实是由文档构建工具从源码自动生成的——它指向的类定义才是真正的内容主体。也就是说要读懂这份命令文档就必须读懂它引用的三个命令类。这正是本文接下来要展开的源码级解读。命令文档还说明了两个关键事实命令即方法Redis 命令在 redis-py 中被封装成客户端对象的同名方法方法名即命令名小写化例如SET→r.set(...)、GET→r.get(...)接口按部署形态划分单机含 Sentinel 托管的主从走CoreCommands哨兵管理面走SentinelCommands集群走RedisClusterCommands。文档原文还提供了一个可以直接运行的入门片段docs/commands.rstimport redis r redis.Redis(decode_responsesTrue) r.set(mykey, thevalueofmykey) r.get(mykey)其中decode_responsesTrue会让服务端返回的bytes自动解码为str日常业务开发中几乎必开。二、CoreCommands单机客户端的命令全集2.1 类定义与混入结构CoreCommands定义在 redis/commands/core.py#L12523-L12536是一个“混入mixin”类通过多继承聚合了 8 组功能命令class CoreCommands( ACLCommands, # 访问控制列表acl_cat / acl_setuser / acl_whoami ... ClusterCommands, # CLUSTER 子命令cluster_info / cluster_slots ... DataAccessCommands, # 数据访问String / Hash / List / Set / ZSet / Stream / Geo / Bitmap ... ManagementCommands, # 管理命令info / config_get / client_list / slowlog_get ... ModuleCommands, # 模块加载module_load / module_loadex / module_list ... PubSubCommands, # 发布订阅publish / pubsub_channels / pubsub_numsub ... ScriptCommands, # Lua 脚本eval / evalsha / script_load ... FunctionCommands, # Redis Functionsfunction_load / fcall / function_stats ... ): A class containing all of the implemented redis commands. This class is to be used as a mixin for synchronous Redis clients.其中DataAccessCommands本身又是一个聚合类redis/commands/core.py#L12487-L12498它把BasicKeyCommandsget/set/expire/ttl…、HashCommands、ListCommands、SetCommands、SortedSetCommands、StreamCommands、GeoCommands、ScanCommands、HyperlogCommands、ArrayCommands全部打包在一起。2.2 命令类如何“长”到客户端上CoreCommands不是独立使用的对象而是作为redis.Redis的基类被继承。在 redis/client.py#L157class Redis(RedisModuleCommands, CoreCommands, SentinelCommands): Implementation of the Redis protocol...也就是说你在文档中看到的“这些函数可以作为 redis 连接上的函数使用”其实现机制就是 Python 的多继承r redis.Redis(...)之后r身上同时拥有CoreCommands的全部方法数据读写、管理、脚本、模块……、RedisModuleCommands提供的 RediSearch/RedisJSON/TimeSeries 等模块门面r.ft()、r.json()、r.ts()以及SentinelCommands的哨兵命令。从源码结构看CoreCommands的每个子命令类如ACLCommands都实现了成对出现的三份方法签名redis/commands/core.py#L116-L135 展示了ACLCommands的写法overload def xxx(self: SyncClientProtocol, ...)—— 同步客户端的类型签名overload def xxx(self: AsyncClientProtocol, ...)—— 异步客户端的类型签名返回Awaitable[...]一个不带overload的真正实现返回类型写成同步返回值 | Awaitable[同步返回值]的联合类型。这种“一方法三签名”的模式贯穿整个 redis/commands/core.py该文件共 12552 行使得同步Redis与异步redis.asyncio.Redis继承AsyncCoreCommands见 redis/commands/core.py#L12539-L12552可以共享同一套命令定义同时保留 IDE 的类型提示。2.3 深入set参数语义与命令构造set是命令文档入门示例的主角它的完整签名定义在 redis/commands/core.py#L4329-L4346下面是在同步/异步双类型下都生效的实现签名def set( self, name: KeyT, value: EncodableT, ex: ExpiryT | None None, # 秒级过期时间 px: ExpiryT | None None, # 毫秒级过期时间 nx: bool False, # 仅当键不存在时写入SET NX xx: bool False, # 仅当键已存在时写入SET XX keepttl: bool False, # 保留原有 TTL get: bool False, # 返回旧值SET GET exat: AbsExpiryT | None None,# 绝对过期时间秒级时间戳 pxat: AbsExpiryT | None None,# 绝对过期时间毫秒级时间戳 ifeq: bytes | str | None None, # 实验性仅当当前值等于该值时写入 ifne: bytes | str | None None, # 实验性仅当当前值不等于该值时写入 ifdeq: str | None None, # 实验性当前值 SHA1/hex 摘要相等时写入 ifdne: str | None None, # 实验性当前值 SHA1/hex 摘要不等时写入 ) - bool | str | bytes | None:语义要点源码 docstringredis/commands/core.py#L4347-L4366ex/px/exat/pxat四者互斥同时传入会抛错nx与xx互斥返回值普通成功返回TruegetTrue时返回旧值键不存在返回Noneifeq/ifne/ifdeq/ifdne自 Redis 7.1 起标记为实验性源码中通过experimental_args([...])装饰器标注redis/commands/core.py#L4329API 可能在后续版本调整生产环境需谨慎。在实现层set内部会把上述关键字参数逐项拼接成SET name value [EX s] [PX ms] [NX|XX] [KEEPTTL] [GET] [EXAT ts] [PXAT ts] ...形式的参数元组最终调用self.execute_command(SET, name, value, *pieces)。2.4 命令执行链路从方法到协议无论哪种命令最终都会汇入Redis.execute_commandredis/client.py#L890-L896def execute_command(self, *args, **options): return self._execute_command(*args, **options) def _execute_command(self, *args, **options): Execute a command and return a parsed response pool self.connection_pool command_name args[0] ...调用链可归纳为命令方法如r.get(mykey)构造参数并调用execute_commandexecute_command从connection_pool取连接命令经编码器Encoder序列化后由连接对象写出响应由解析器RESP2/RESP3见 redis/_parsers 目录按命令注册的回调response callbacks转换成 Python 对象dict/list/bool/int…返回。Pipeline管道场景下Pipeline类同样继承自Redisredis/client.py#L1820并重写execute_commandredis/client.py#L1919-L1922非事务模式下命令被排队到pipeline_execute_command最后一次性发送减少网络往返transactionTrue默认时所有命令以 MULTI/EXEC 原子执行。客户端入口为r.pipeline(transactionTrue)redis/client.py#L628-L634。三、SentinelCommands哨兵管理命令3.1 类定义SentinelCommands定义在 redis/commands/sentinel.py#L12-L16class SentinelCommands: A class containing the commands specific to redis sentinel. This class is to be used as a mixin.注意它与CoreCommands的差异Sentinel 命令只能在哨兵节点上执行因此它没有继承CoreCommands而是独立的一层。异步版本AsyncSentinelCommands继承自SentinelCommandsredis/commands/sentinel.py#L255-L258。3.2 方法清单对应 SENTINEL 子命令该类把SENTINEL subcommand拆解为一个个 Python 方法redis/commands/sentinel.py方法对应命令说明sentinel_get_master_addr_by_name(service_name, return_responsesFalse)SENTINEL GET-MASTER-ADDR-BY-NAME返回 master 的 (host, port)可用于自定义主从发现sentinel_master(service_name)SENTINEL MASTER返回单个 master 的详细信息字典sentinel_masters()SENTINEL MASTERS返回所有被监控 master 的信息sentinel_monitor(name, ip, port, quorum)SENTINEL MONITOR动态添加一个被监控的 mastersentinel_remove(name)SENTINEL REMOVE移除监控sentinel_sentinels(service_name)SENTINEL SENTINELS返回监控同一 master 的其他哨兵列表sentinel_slaves(service_name)SENTINEL SLAVES返回该 master 的从节点列表sentinel_set(name, option, value)SENTINEL SET修改 master 配置sentinel_reset(pattern)SENTINEL RESET重置匹配的 master 状态sentinel_failover(new_master_name)SENTINEL FAILOVER强制发起一次故障切换sentinel_ckquorum(new_master_name)SENTINEL CKQUORUM检查法定人数是否满足sentinel_flushconfig()SENTINEL FLUSHCONFIG将配置刷写到哨兵配置文件此外还有一个通用方法sentinel(*args)但源码中已用DeprecationWarning标记废弃redis/commands/sentinel.py#L18-L20官方建议改用上述sentinel_*方法。所有方法都支持return_responsesTrue以拿到哨兵的原始响应而不是统一的布尔值。3.3 Sentinel 高层客户端命令文档里提到的“连接上的函数”在哨兵场景下有两层含义低层普通Redis客户端本身就继承了SentinelCommandsredis/client.py#L157所以redis.Redis(hostsentinel1, port26379)实例可以直接调用sentinel_masters()等命令高层redis/sentinel.py#L224-L251 的Sentinel类封装了节点发现、主从切换与连接池管理典型用法如下出自该类 docstringfrom redis.sentinel import Sentinel sentinel Sentinel([(localhost, 26379)], socket_timeout0.1) master sentinel.master_for(mymaster, socket_timeout0.1) master.set(foo, bar) slave sentinel.slave_for(mymaster, socket_timeout0.1) slave.get(foo)关键参数sentinels哨兵节点(host, port)列表至少一个min_other_sentinels哨兵被认定为有效所需的最少对等节点数默认 0sentinel_kwargs连接哨兵时的参数缺省时自动复用connection_kwargs中以socket_开头的选项redis/sentinel.py#L261-L267connection_kwargs连接真实 Redis 主从时的参数如password、socket_timeout。Sentinel.execute_command默认向所有哨兵节点广播命令并返回all(responses)传入onceTrue则随机挑一个节点执行redis/sentinel.py#L277-L303。master_for/slave_for返回的客户端通过SentinelConnectionPool自动感知故障切换切换后无需重启应用。四、RedisClusterCommands集群命令与哈希槽路由4.1 类定义RedisClusterCommands定义在 redis/commands/cluster.py#L1487-L1497class RedisClusterCommands( ClusterMultiKeyCommands, # 多 key 命令MGET/MSET/EXISTS/DELETE...按槽拆分 ClusterManagementCommands,# CLUSTER 管理命令cluster_addslots / cluster_failover ... ACLCommands, PubSubCommands, ClusterDataAccessCommands, ScriptCommands, FunctionCommands, ModuleCommands, RedisModuleCommands, ): A class for all Redis Cluster commands For key-based commands, the target node(s) will be internally determined by the keys hash slot.docstring 中的关键句“对于基于 key 的命令目标节点由 key 的哈希槽在内部自动确定。”这正是集群客户端与单机客户端最大的区别。异步版本AsyncRedisClusterCommands位于 redis/commands/cluster.py#L1518-L1528。4.2 集群专属命令ClusterManagementCommands提供了仅在集群中有效的命令例如cluster_addslots(target_node, *slots)/cluster_delslots(*slots)分配/释放槽cluster_setslot(target_node, node_id, slot_id, state)迁移槽位状态cluster_failover(target_node, optionNone)手动故障转移cluster_info(target_nodesNone)集群信息cluster_nodes()节点拓扑返回dict[str, ClusterNodeDetail]cluster_keyslot(key)计算某个 key 所属的槽cluster_get_keys_in_slot(slot, num_keys)取槽内 keycluster_shards()/cluster_myid()/cluster_myshardid()等较新命令。这些命令在 redis/commands/cluster.py 中同样采用“同步 overload 异步 overload 联合实现”三签名模式多数还支持target_node/target_nodes参数以指定在哪个节点上执行。4.3 多 key 命令的槽感知实现ClusterMultiKeyCommands是集群客户端最有特色的部分当一条命令涉及多个 key 时它会按 key 的哈希槽进行分组。以mget/mset为例源码提供了两种策略redis/commands/cluster.pymget(keys)/mset(mapping)要求所有 key 落在同一槽否则抛RedisClusterException——这是为了保持原子性mget_nonatomic(keys)/mset_nonatomic(mapping)允许 key 分散在不同槽内部通过_partition_keys_by_slot按槽分组、_execute_pipeline_by_slot逐槽执行管道再用_reorder_keys_by_command按原始 key 顺序重组结果见 redis/commands/cluster.py 中_partition_keys_by_slot、_partition_pairs_by_slot、_execute_pipeline_by_slot、_reorder_keys_by_command等私有方法。同样exists/delete/touch/unlink的多 key 变体会调用_split_command_across_slots把命令拆到多个槽分别执行后汇总计数。4.4 集群客户端接入RedisCluster类定义在 redis/cluster.py#L653-L657class RedisCluster( AbstractRedisCluster, MaintNotificationsAbstractRedisCluster, RedisClusterCommands ): _is_async_client: Literal[False] False典型用法官方文档示例风格from redis.cluster import RedisCluster # 连接任意一个节点即可客户端会通过 CLUSTER SLOTS 自动发现拓扑 rc RedisCluster(host127.0.0.1, port7000) rc.set(foo, bar) rc.get(foo) rc.close()注意slaveof、replicaof、swapdb等在集群模式下没有意义RedisClusterCommands中已将这三者实现为直接抛错的方法见 redis/commands/cluster.py。异步场景使用redis.asyncio.cluster.RedisCluster继承AsyncRedisClusterCommands。五、命令类的发布入口与模块扩展5.1redis.commands包的统一出口上述所有命令类都通过 redis/commands/init.py 统一导出from .cluster import READ_COMMANDS, AsyncRedisClusterCommands, RedisClusterCommands from .core import AsyncCoreCommands, CoreCommands from .helpers import list_or_args from .redismodules import AsyncRedisModuleCommands, RedisModuleCommands from .sentinel import AsyncSentinelCommands, SentinelCommands __all__ [ AsyncCoreCommands, AsyncRedisClusterCommands, AsyncRedisModuleCommands, AsyncSentinelCommands, CoreCommands, READ_COMMANDS, RedisClusterCommands, RedisModuleCommands, SentinelCommands, list_or_args, ]因此你可以直接from redis.commands import CoreCommands, SentinelCommands, RedisClusterCommands做类型标注或自定义客户端组装这也呼应了命令文档中autoclass指向的正是这三个类的行为。5.2 Redis 模块命令命令文档之外的门面虽然docs/commands.rst只列出三类命令但CoreCommands体系并未止步于原生 Redis 命令RedisModuleCommandsredis/commands/redismodules.py通过json()/ft()/ts()/bf()/vset()等方法把 RediSearch、RedisJSON、TimeSeries、Bloom 等模块客户端挂载到Redis实例上使r.json().set(...)、r.ft(idx).search(...)成为可能。这解释了为何Redis类的基类列表中同时出现RedisModuleCommands, CoreCommands, SentinelCommandsredis/client.py#L157。六、同步与异步的命令一致性命令文档中autoclass生成的 API 同时服务同步与异步客户端。从源码看一致性由两点保证命令定义共享AsyncCoreCommands与CoreCommands的 8 个构成命令类共享底层实现异步类只是把方法包装为async def并返回Awaitable[...]redis/commands/core.py#L12539-L12552同一套调用约定同步写法r.set(...)与异步写法await r.set(...)参数完全一致。异步示例对应redis/asyncio客户端import asyncio from redis.asyncio import Redis async def main(): r Redis(decode_responsesTrue) await r.set(mykey, thevalueofmykey) value await r.get(mykey) print(value) # thevalueofmykey await r.aclose() asyncio.run(main())同步客户端入口为 redis/client.py异步客户端入口为 redis/asyncio/client.py两者命令集对齐。七、结合测试与示例验证命令用法仓库中针对各命令族的测试覆盖了本文介绍的全部路径可作为查阅参数语义和返回值的权威参考核心数据命令tests/test_commands.pyString/Hash/List/Set/ZSet/Stream/Geo 等集群命令tests/test_cluster.py、tests/test_asyncio/test_cluster.pySentinel 命令tests/test_sentinel.py、tests/test_asyncio/test_sentinel.py管道tests/test_pipeline.py、tests/test_asyncio/test_pipeline.py连接与响应解析tests/test_connection.py、tests/test_parsers/。入门示例还可见于 docs/examples 下的 notebook如set_and_get_examples.ipynb、connection_examples.ipynb、pipeline_examples.ipynb以及 doctests 目录中可实际运行的脚本如 doctests/string_set_get.py、doctests/trans_pipe.py。八、速查三种命令入口对比维度CoreCommandsSentinelCommandsRedisClusterCommands定义位置redis/commands/core.py#L12523redis/commands/sentinel.py#L12redis/commands/cluster.py#L1487覆盖范围全部原生命令ACL/数据/管理/PubSub/Script/Function/Module…仅 SENTINEL 子命令集群管理 原生命令 多 key 槽拆分使用对象Redisredis/client.py#L157Redis实例或Sentinelredis/sentinel.py#L224RedisClusterredis/cluster.py#L653异步版本AsyncCoreCommandsAsyncSentinelCommandsAsyncRedisClusterCommands典型方法set/get/hset/zadd/xadd/eval…sentinel_masters/sentinel_failover…cluster_info/cluster_keyslot/mget_nonatomic…结语docs/commands.rst虽然篇幅短小但它定义的是 redis-py 的“命令门面”设计所有命令方法都是可复用的混入类按部署形态单机 / Sentinel / Cluster与功能域数据 / 管理 / 脚本 / 模块两个维度组织同步与异步共享同一套定义。理解了这个架构无论是阅读 redis/commands/core.py、redis/commands/sentinel.py 还是 redis/commands/cluster.py你都能快速定位任意命令的实现、参数与返回类型在实际开发中也能根据“单机选redis.Redis、高可用选Sentinel、水平扩展选RedisCluster”的原则准确选择接入方式并善用mget_nonatomic、scan_iter、Pipeline 等客户端侧能力写出更高效的代码。【免费下载链接】redis-pyRedis Python client项目地址: https://gitcode.com/GitHub_Trending/re/redis-py创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表