资讯详情

资讯详情

Hyperf Redis 组件全解析:连接池代理、多库切换与 Sentinel/Cluster 高可用实战

后端Web框架微服务RPC框架异步编程【免费下载链接】hyperf A coroutine framework that focuses on hyperspeed and flexibility. Building microservice or middleware with ease.项目地址https://gitcode.com/hyperf/hyperf点击查看免费下载导读hyperf/redis是 Hyperf 框架内置的 Redis 客户端组件它在ext-redisphpredis扩展之上封装了连接池与协程上下文机制让开发者可以像使用原生\Redis一样通过依赖注入容器直接获得可安全运行于 Swoole/Swow 协程环境中的 Redis 代理对象。本指南以 docs/id/redis.md 为核心骨架结合组件源码src/redis与发布配置publish/redis.php完整讲解安装配置、连接池参数、多数据库连接、Sentinel 哨兵模式、Cluster 集群模式以及options高级选项。读完本文你将掌握在 Hyperf 项目中配置一套生产可用 Redis 客户端的完整方案并能根据业务场景选择 Proxy Class 或 Factory Class 两种多库使用方式。安装与配置发布安装组件在项目根目录执行 Composer 命令安装组件composer require hyperf/redis安装完成后组件的ConfigProvider会自动注册两项能力见 src/redis/src/ConfigProvider.php依赖绑定将原生\Redis::class绑定到 Hyperf 的Redis代理类容器中获取\Redis时实际得到的是池化代理对象配置发布将 publish/redis.php 发布到项目的config/autoload/redis.php。执行以下命令即可生成完整配置文件php bin/hyperf.php vendor:publish hyperf/redis发布后即可在config/autoload/redis.php中按需修改配置。核心配置参数发布出的默认配置以default为连接池名称全部参数如下表配置项类型默认值说明hoststringlocalhostRedis 服务器地址authstringnullRedis 实例密码portinteger6379Redis 端口dbinteger0默认使用的逻辑数据库编号timeoutfloat0.0连接超时时间秒reservedmixednullphpredisconnect()的保留参数通常传nullretry_intervalinteger0连接失败后的重试间隔毫秒read_timeoutfloat0.0读取超时时间秒0表示不限制cluster.enablebooleanfalse是否启用 Cluster 集群模式cluster.namestringnull集群名称对应redis.ini中配置的redis.clusters.seedscluster.seedsarray[]集群节点地址数组格式[host:port]sentinel.enablebooleanfalse是否启用 Sentinel 哨兵模式sentinel.master_namestringmymaster哨兵监控的主节点名称sentinel.nodesarray[]哨兵节点列表可通过explode(;, env(REDIS_SENTINEL_NODE))拆分sentinel.persistentboolean/string是否持久连接sentinel.read_timeoutfloat0哨兵读取超时sentinel.authstring哨兵节点自身的认证密码pool.min_connectionsinteger1连接池最小连接数pool.max_connectionsinteger10连接池最大连接数pool.connect_timeoutfloat10.0从池中获取连接的超时时间pool.wait_timeoutfloat3.0等待连接可用的超时时间pool.heartbeatinteger-1心跳检测间隔秒-1表示不启用pool.max_idle_timefloat60连接最大空闲时间秒optionsobject{}透传给 phpredis 的setOption()选项键可为常量或字符串event.enablebooleanfalse是否派发命令执行事件CommandExecuted一个典型的最小配置如下?php return [ default [ host env(REDIS_HOST, localhost), auth env(REDIS_AUTH, ), port (int) env(REDIS_PORT, 6379), db (int) env(REDIS_DB, 0), cluster [ enable (bool) env(REDIS_CLUSTER_ENABLE, false), name null, seeds [], ], pool [ min_connections 1, max_connections 10, connect_timeout 10.0, wait_timeout 3.0, heartbeat -1, max_idle_time (float) env(REDIS_MAX_IDLE_TIME, 60), ], options [ \Redis::OPT_PREFIX env(REDIS_PREFIX, ), // 或使用字符串键 prefix env(REDIS_PREFIX, )适用于 phpredis v3.0.38低版本需使用常量键 ], ], ];说明options同时支持常量键如\Redis::OPT_PREFIX与字符串键如prefix。从源码 RedisConnection.php 可以看到字符串键会被统一映射为对应常量serializer、prefix、read_timeout、scan、failover、keepalive、compression、reply_literal、compression_level未知字符串键会抛出InvalidRedisOptionException。连接池与代理机制hyperf/redis的核心价值在于你拿到的\Redis并不是裸客户端而是池化代理。文档原文明确指出组件实现了ext-redis的代理proxy与连接池connection pool通过容器注入\Hyperf\Redis\Redis后实际得到的是\Redis的代理对象。最基础的用法?php use Hyperf\Context\ApplicationContext; $container ApplicationContext::getContainer(); $redis $container-get(\Hyperf\Redis\Redis::class); $result $redis-keys(*);在协程环境中裸\Redis连接跨协程共享会产生数据错乱与阻塞问题。代理类在每次命令调用时完成三件事见 src/redis/src/Redis.php取连接优先从协程上下文key 为redis.connection.{poolName}复用当前协程已持有的连接不存在则通过PoolFactory从对应连接池获取Redis.php执行命令把调用通过__call转发给底层RedisConnection由后者再转发给真实的 phpredis 客户端RedisConnection.php并记录耗时、派发CommandExecuted事件归还连接普通命令执行后立即release()归还连接池而multi、pipeline、select这类需要“同一连接”的命令会先把连接存入协程上下文再用defer()在协程退出时归还Redis.php从而保证事务/管道的原子性。连接池本身由 RedisPool 实现它从redis.{name}配置段读取pool子配置并交由 Hyperf 通用池框架管理连接的创建、心跳与回收连接对象 RedisConnection 在reconnect()时会根据cluster.enable/sentinel.enable选择创建RedisCluster、哨兵解析出的主节点连接或普通Redis连接并统一应用options、执行auth()与select()。此外底层连接在命令执行失败时会自动执行一次retry()记录日志、重建连接并重放该命令RedisConnection.php增强了网络抖动场景下的容错能力。多数据库配置真实项目中单一数据库往往不够用此时可在config/autoload/redis.php中为不同业务分别命名连接池。文档给出了一个名为foo的示例db设为1?php return [ default [ host env(REDIS_HOST, localhost), auth env(REDIS_AUTH, ), port (int) env(REDIS_PORT, 6379), db (int) env(REDIS_DB, 0), cluster [ enable (bool) env(REDIS_CLUSTER_ENABLE, false), name null, seeds [], ], pool [ min_connections 1, max_connections 10, connect_timeout 10.0, wait_timeout 3.0, heartbeat -1, max_idle_time (float) env(REDIS_MAX_IDLE_TIME, 60), ], ], // 新增名为 foo 的 Redis 连接池 foo [ host env(REDIS_HOST, localhost), auth env(REDIS_AUTH, ), port (int) env(REDIS_PORT, 6379), db 1, pool [ min_connections 1, max_connections 10, connect_timeout 10.0, wait_timeout 3.0, heartbeat -1, max_idle_time (float) env(REDIS_MAX_IDLE_TIME, 60), ], ], ];需要说明的是RedisPool在构造时会校验配置项是否存在读取redis.{name}若不存在会抛出InvalidArgumentException(config[redis.{name}] is not exist!)RedisPool.php因此多池配置必须保证每个名称都有完整的配置段。方式一Proxy Class继承代理类为每个固定业务场景定义一个继承Hyperf\Redis\Redis的代理子类重写poolName属性指向对应连接池?php use Hyperf\Redis\Redis; class FooRedis extends Redis { // 对应连接池的 key 名称 protected $poolName foo; } // 通过容器 DI 获取当前类实例 $redis $this-container-get(FooRedis::class); $result $redis-keys(*);这种方式的好处是每个类对应一个固定的数据库语义配合依赖注入可以做到“按需注入、语义清晰”。代理类poolName的机制在 Redis.php 与 RedisProxy.php 中均有体现——RedisProxy正是通过构造参数动态指定poolName的通用实现。方式二Factory Class工厂动态获取当数据库与业务场景并非一一对应、需要动态切换时可用Hyperf\Redis\RedisFactory按池名即时获取客户端无需为每个库编写代理类?php use Hyperf\Redis\RedisFactory; use Hyperf\Context\ApplicationContext; $container ApplicationContext::getContainer(); // 通过容器 DI 获取 RedisFactory再按池名获取客户端 $redis $container-get(RedisFactory::class)-get(foo); $result $redis-keys(*);从源码看RedisFactory在构造时会遍历redis配置段下所有连接池并为每个池预先构建一个RedisProxy实例缓存起来RedisFactory.phpget($poolName)直接命中缓存若传入不存在的池名会抛出InvalidRedisProxyExceptionRedisFactory.php。Sentinel 哨兵模式当 Redis 以主从 Sentinel 方式部署时需要启用哨兵模式。文档给出的.env配置如下多个哨兵节点使用;分隔REDIS_HOST REDIS_AUTHRedis 实例密码 REDIS_PORT REDIS_DB REDIS_SENTINEL_ENABLEtrue REDIS_SENTINEL_PASSWORDSentinel 节点密码 REDIS_SENTINEL_NODE192.168.89.129:26381;192.168.89.129:26380;对应的redis.php配置?php return [ default [ host env(REDIS_HOST, localhost), auth env(REDIS_AUTH, null), port (int) env(REDIS_PORT, 6379), db (int) env(REDIS_DB, 0), timeout 30.0, reserved null, retry_interval 0, sentinel [ enable (bool) env(REDIS_SENTINEL_ENABLE, false), master_name env(REDIS_MASTER_NAME, mymaster), nodes explode(;, env(REDIS_SENTINEL_NODE, )), persistent false, read_timeout 30.0, auth env(REDIS_SENTINEL_PASSWORD, ), ], pool [ min_connections 1, max_connections 10, connect_timeout 10.0, wait_timeout 3.0, heartbeat -1, max_idle_time (float) env(REDIS_MAX_IDLE_TIME, 60), ], ], ];哨兵模式的工作流程可以从源码得到印证RedisConnection.php读取sentinel.nodes列表并shuffle()打乱顺序实现哨兵节点的负载均衡依次尝试连接每个哨兵节点节点地址通过parse_url解析出host与port调用RedisSentinel::getMasterAddrByName($master_name)查询当前主节点地址一旦某个哨兵返回了合法的[host, port]就基于该地址创建真正的 Redis 连接全部失败则抛出InvalidRedisConnectionException。哨兵连接对象的创建由 RedisSentinelFactory 负责它会根据本机 phpredis 扩展版本自动适配构造方式redis扩展低于 6.0.0 时使用旧式位置参数构造6.0 及以上使用数组参数构造。因此在使用哨兵模式前请确认扩展版本并正确填写REDIS_SENTINEL_NODE、REDIS_SENTINEL_PASSWORD等环境变量。Cluster 集群模式启用集群模式只需将cluster.enable设为true。源码中 RedisConnection.php 的createRedisCluster()会将name、seeds、timeout、read_timeout、persistent、auth依次透传给new RedisCluster(...)因此name与seeds二选一即可满足 phpredis 集群构造要求。方式一通过name使用预配置集群先在 PHP 配置文件或Dockerfile中预置集群信息。文档给出的 Dockerfile 片段# - PHP 配置 { \ echo upload_max_filesize100M; \ echo post_max_size108M; \ echo memory_limit1024M; \ echo date.timezone${TIMEZONE}; \ echo redis.clusters.seeds \mycluster[]localhost:7000mycluster[]localhost:7001\; \ echo redis.clusters.timeout \mycluster5\; \ echo redis.clusters.read_timeout \mycluster10\; \ echo redis.clusters.auth \myclusterpassword\; } | tee conf.d/99-overrides.ini随后在redis.php中只配置集群名称即可?php // 其余配置略 return [ default [ cluster [ enable true, name mycluster, seeds [], ], ], ];这种方式下phpredis 会根据redis.ini中redis.clusters.*预置的节点、超时与密码自动建立集群连接适合在容器镜像中统一管理集群参数。方式二通过seeds直接指定节点不配置name直接在seeds中列出节点地址?php // 其余配置略 return [ default [ cluster [ enable true, name null, seeds [ 192.168.1.110:6379, 192.168.1.111:6379, ], ], ], ];两种方式等价地影响createRedisCluster()的构造参数传入了非空name时使用预配置集群否则以seeds数组作为节点种子。实际部署时只需保证seeds中的节点至少覆盖集群的一个主节点即可完成拓扑发现。options 高级选项options会通过\Redis::setOption()应用到每个连接RedisConnection.php。文档给出两个典型场景。示例一切换为 PHP 序列化将 Redis 默认的序列化方式改为 PHP 序列化便于存取对象等复合类型?php declare(strict_types1); return [ default [ host env(REDIS_HOST, localhost), auth env(REDIS_AUTH, null), port (int) env(REDIS_PORT, 6379), db (int) env(REDIS_DB, 0), pool [ min_connections 1, max_connections 10, connect_timeout 10.0, wait_timeout 3.0, heartbeat -1, max_idle_time (float) env(REDIS_MAX_IDLE_TIME, 60), ], options [ \Redis::OPT_SERIALIZER \Redis::SERIALIZER_PHP, // 或 serializer \Redis::SERIALIZER_PHP适用于 phpredis v3.0.38低版本需使用常量键 ], ], ];示例二设置永不超时将读取超时设为-1Redis 命令将不会因读取等待而超时适用于长时间阻塞类操作如BLPOP等?php declare(strict_types1); return [ default [ host env(REDIS_HOST, localhost), auth env(REDIS_AUTH, null), port (int) env(REDIS_PORT, 6379), db (int) env(REDIS_DB, 0), pool [ min_connections 1, max_connections 10, connect_timeout 10.0, wait_timeout 3.0, heartbeat -1, max_idle_time (float) env(REDIS_MAX_IDLE_TIME, 60), ], options [ \Redis::OPT_READ_TIMEOUT -1, // 或 read_timeout -1适用于 phpredis v3.1.3低版本需使用常量键 ], ], ];注意对部分 phpredis 扩展版本options中的value必须为string类型否则setOption()可能失败请结合本机扩展版本文档核对。事件与可观测性发布配置中还包含event.enable开关。开启后每次 Redis 命令执行完毕都会派发Hyperf\Redis\Event\CommandExecuted事件事件携带命令名称、参数、耗时毫秒、连接对象、所属连接池名称、执行结果与异常信息Redis.php。配合 Hyperf 的事件监听器与日志系统可以低成本实现 Redis 命令的慢查询监控、埋点统计等可观测能力?php // 在 config/autoload/redis.php 中开启 return [ default [ // ... event [ enable (bool) env(REDIS_EVENT_ENABLE, false), ], ], ];对应的事件类位于 src/redis/src/Event/CommandExecuted.php监听器可通过实现Hyperf\Event\Contract\ListenerInterface订阅该事件。小结通过本文你已掌握hyperf/redis组件的完整使用链路安装发布composer require hyperf/redisphp bin/hyperf.php vendor:publish hyperf/redis基础使用容器注入\Hyperf\Redis\Redis底层自动完成连接池获取、命令执行与归还且multi/pipeline/select在协程上下文保持同一连接多库方案静态场景用 Proxy Class 继承重写poolName动态场景用RedisFactory::get($poolName)高可用Sentinel 模式通过sentinel.*配置自动发现主节点并容错切换Cluster 模式通过cluster.name或cluster.seeds接入集群精细调优pool.*控制池化行为options透传 phpredis 选项序列化、前缀、超时等event.enable开启命令事件可观测。以上配置与源码路径均可在当前仓库 src/redis 中继续深入研读测试用例如 tests/RedisTest.php、tests/RedisProxyTest.php也覆盖了连接池、代理与哨兵/集群的构造逻辑可作为理解底层行为的补充材料。赞分享后端Web框架微服务RPC框架异步编程【免费下载链接】hyperf A coroutine framework that focuses on hyperspeed and flexibility. Building microservice or middleware with ease.项目地址https://gitcode.com/hyperf/hyperf点击查看免费下载相关推荐Tiny RDM连接Redis Sentinel哨兵模式与Cluster集群模式高可用部署实战指南Tiny RDM连接Redis Sentinel哨兵模式与Cluster集群模式高可用部署实战指南 Tiny RDMTiny Redis Desktop M数据库客户端桌面应用终极指南如何利用redis-py实现高可用Redis连接池与主从无缝切换终极指南如何利用redis py实现高可用Redis连接池与主从无缝切换 在现代应用架构中Redis作为高性能的内存数据库其高可用性至关重要。redis后端数据库客户端缓存Hyperf Redis 客户端使用指南连接池、多资源、哨兵与集群模式全解析Hyperf Redis 客户端使用指南连接池、多资源、哨兵与集群模式全解析 Hyperf 框架内置的 hyperf/redis 组件是 ext redis后端Web框架微服务RPC框架异步编程上一篇mistral.rs 统一多模态推理示例解析一个 Rust 程序驱动 20 主流视觉模型下一篇Home Assistant Motionblinds 绝对位置控制指南深入解析 motion_blinds.set_absolute_position 动作创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →