hyperf 3.1 实现读写分离与主从负载均衡的关键在于路由策略精准、连接池隔离和协程安全复用:需显式配置 mysql-write(主库)和 mysql-read(多从库轮询)两个独立连接池;读写操作须手动指定连接名,事务强制走主库;强一致性读直连主库,延迟敏感场景需监控 seconds_behind_master 并动态剔除异常从库;进阶可结合 proxysql 实现 sql 层智能路由。

Hyperf 3.1 在协程环境下实现数据库读写分离与主从负载均衡,关键不在“加节点”,而在于路由策略精准 + 连接池隔离 + 协程安全复用。配置错一步,比如把读请求发到主库、或让事务跨从库执行,就可能引发数据不一致或连接污染。
主从节点定义与连接池分离
Hyperf 不自动识别主从角色,需在 config/autoload/databases.php 中显式声明:
- 定义两个独立连接池:一个叫
mysql-write(指向主库),一个叫mysql-read(可配多个从库) -
mysql-read的url支持数组格式,Hyperf 会自动轮询(Round-Robin)分发读请求:
url => ['mysql://user:pass@192.168.1.11:3306/db', 'mysql://user:pass@192.168.1.12:3306/db'] - 每个池都需独立配置连接池参数(如
min_connections、max_connections),避免读写争抢同一连接资源
读写路由逻辑配置
Hyperf 默认不自动区分 SELECT 和 INSERT,必须通过 db 组件的 read/write 方法或中间件手动控制:
- 写操作强制走主库:
DB::connection('mysql-write')->insert(...) - 读操作走从库池:
DB::connection('mysql-read')->select(...) - 若使用 Eloquent,可在模型中重写
getConnectionName()方法,根据方法名或上下文动态返回mysql-read或mysql-write - 事务内所有操作必须统一走主库——
DB::transaction()会自动绑定到mysql-write,切勿在事务中混用mysql-read
协程安全与延迟容忍处理
主从复制天然存在延迟,Hyperf 协程环境更需主动应对,否则刚写入就查不到:
- 对强一致性读(如“下单后立即查订单”),直接走
mysql-write,不绕弯 - 避免在协程中用
sleep()等待从库同步;可用co::sleep(0.1)配合重试逻辑,但应尽量减少 - 监控
Seconds_Behind_Master,若某从库延迟超阈值(如 > 5s),可在运行时临时将其从mysql-read的 URL 数组中剔除(需配合健康检查) - 确保 MySQL 主从
binlog_format = ROW且server-id全局唯一,否则复制中断会导致读节点数据停滞
进阶:结合 ProxySQL 做 SQL 层智能路由
若不想在应用层硬编码读写逻辑,可部署 ProxySQL 作为透明中间件:
- Hyperf 应用只连 ProxySQL(如
127.0.0.1:6033),完全无感 - 在 ProxySQL 中配置规则:
^SELECT.*FOR UPDATE → 主库 hostgroup
^SELECT → 从库 hostgroup(支持权重、延迟感知) - ProxySQL 自动处理故障转移、慢查询熔断、连接复用,比纯应用层方案更稳定
- 注意:ProxySQL 本身不支持协程,但作为 TCP 代理对 Hyperf 无影响;只需确保其监听端口可达、认证正确











