Hyperf需结合数据库高可用机制与框架层适配实现故障转移:MySQL依赖自定义ReadWriteProxyDriver实现主从探测与降级,Redis需配置phpredis哨兵或集群模式,并严格设置连接池超时与心跳参数。

Hyperf 本身不内置多数据库自动故障转移能力,必须结合底层数据库高可用机制(如 MySQL 主从+GTID、Redis 哨兵/集群)和框架层主动适配才能实现。关键不是“开个开关”,而是三件事:连接池韧性设计、客户端驱动支持故障感知、应用层兜底切换逻辑。
MySQL 主从场景:靠 PDO 连接池 + 自定义读写分离驱动
Hyperf 的 Db 组件默认只连一个 host,要支持主从自动切换,不能只改 config/autoload/db.php,得替换底层驱动:
- 在
config/autoload/db.php中定义多个连接配置,例如mysql-master和mysql-slave - 编写自定义
ReadWriteProxyDriver,继承Hyperf\Database\Connectors\MysqlConnector,重写createConnection() - 在连接建立时主动探测主库健康状态(如执行
SELECT 1),失败则降级走从库;从库异常时跳过该节点,轮询其余从库 - 把该驱动注册进 DI 容器,在
dependencies.php中绑定:$container->set(MySqlDriver::class, ReadWriteProxyDriver::class) - 注意:事务内强制走主库,避免主从延迟导致数据不一致;非事务查询才可路由到从库
Redis 故障转移:优先用 phpredis 的 RedisSentinel 或 RedisCluster
别用默认单点 Redis 配置。Hyperf 支持原生哨兵和集群模式,但需显式启用:
- 安装 phpredis 扩展并启用
redis.sentinel或redis.cluster配置项 - 在
config/autoload/redis.php中配置哨兵列表:'sentinels' => [['host' => '192.168.1.10', 'port' => 26379]],并设'master_name' => 'mymaster' - 若用集群,填
'servers' => [['host' => '192.168.1.20', 'port' => 6379], ...],同时开启'cluster' => true - 连接池必须配
'connect_timeout' => 2.0、'wait_timeout' => 3.0,避免故障节点拖慢整体响应 - 测试时可手动 kill 主节点,观察客户端是否在 1–2 秒内完成重定向
连接池与超时:防止“假死”掩盖真实故障
很多故障转移失效,其实是连接池卡在无效连接上,没及时释放或重建:
- MySQL 连接池中,
pool.max_idle_time设为 30 秒以内,避免空闲连接被中间件或防火墙断开后仍被复用 - Redis 连接池启用
heartbeat(如设为 30),配合服务端timeout 60,防止静默断连 - 所有数据库连接配置里,
options.ATTR_TIMEOUT必须明确设为 3–5 秒,否则 PDO 默认无超时,协程会无限等待 - 日志中出现
MySQL server has gone away或Connection refused时,不是加 retry 就行,先检查连接池是否已回收坏连接
运行时监控与人工干预入口
自动转移不是万能的,得留出可观测性和手动接管路径:
- 用
hyperf/watcher或 Prometheus Exporter 暴露当前主库地址、从库存活数、最近一次切换时间等指标 - 提供 HTTP 接口(如
/admin/db/status)返回各节点健康状态,支持 curl 触发强制切换 - 在 Supervisor 或 systemd 的 restart 策略里加 delay(如
RestartSec=5),避免雪崩式重启 - 记录每次故障转移的上下文(SQL、时间、触发原因),便于回溯是否是误判或网络抖动











