PHP读写分离权重怎么配

wen PHP项目 1

本文目录导读:

PHP读写分离权重怎么配

  1. 使用 Laravel (框架层面)
  2. 使用 ThinkPHP 6.0+ (框架层面)
  3. 使用 PHP 原生 + PDO (自研封装)
  4. 使用数据库中间件 (最推荐)
  5. 主从延迟与权重的关系(重要)
  6. 推荐配置层级
  7. 注意事项

在 PHP 中配置读写分离权重,通常需要结合数据库中间件ORM 框架自研封装来实现,下面列出几种常见的配置方式,从框架层面到中间件层面。


使用 Laravel (框架层面)

Laravel 原生支持读写分离,但不支持权重,要实现权重负载,需要结合第三方包或自定义逻辑。

① 原生配置(无权重,随机/轮询)

// config/database.php
'mysql' => [
    'read' => [
        'host' => [
            '192.168.1.1',
            '192.168.1.2',
            '192.168.1.3',
        ],
    ],
    'write' => [
        'host' => [
            '192.168.1.100',
        ],
    ],
    'sticky'    => true,
    'driver'    => 'mysql',
    'database'  => 'schema',
    'username'  => 'root',
    'password'  => '',
    'charset'   => 'utf8mb4',
],

② 使用第三方包(支持权重) 推荐包:laravel-doctrine 或自定义连接器。

// 自定义服务提供者中绑定连接器
use Illuminate\Database\Connection;
use Illuminate\Database\Connectors\MySqlConnector;
$this->app->bind('db.connector.mysql', function ($app, $config) {
    // 重写 createConnection 方法,在内部实现权重随机算法
});

使用 ThinkPHP 6.0+ (框架层面)

ThinkPHP 6 支持读写分离,并且支持权重配置

核心配置:

// config/database.php
return [
    'connections' => [
        'mysql' => [
            'type'     => 'mysql',
            'host'     => '192.168.1.100', // 主库(写)
            'username' => 'root',
            'password' => '',
            'database' => 'demo',
            // 读写分离配置
            'rw_separate' => true,
            'read' => [
                'host' => [
                    // 格式:'权重' => '主机'
                    'weight' => [
                        '192.168.1.1' => 3,  // 权重3
                        '192.168.1.2' => 2,  // 权重2
                        '192.168.1.3' => 1,  // 权重1
                    ],
                ],
                'username' => 'root',
                'password' => '',
            ],
        ],
    ],
];

备注:ThinkPHP 内置了 parseWeight 方法,会按照权重比例随机选取从库。


使用 PHP 原生 + PDO (自研封装)

自己写一个数据库连接管理器,实现权重随机。

class DatabaseManager
{
    private $readHosts = [
        ['host' => '192.168.1.1', 'weight' => 3],
        ['host' => '192.168.1.2', 'weight' => 2],
        ['host' => '192.168.1.3', 'weight' => 1],
    ];
    private $writeHost = ['host' => '192.168.1.100'];
    /**
     * 根据权重随机选择从库
     */
    private function selectReadHost()
    {
        $totalWeight = array_sum(array_column($this->readHosts, 'weight'));
        $rand = mt_rand(1, $totalWeight);
        foreach ($this->readHosts as $host) {
            $rand -= $host['weight'];
            if ($rand <= 0) {
                return $host['host'];
            }
        }
        return $this->readHosts[0]['host'];
    }
    /**
     * 获取 PDO 连接
     */
    public function getConnection($isWrite = false)
    {
        $host = $isWrite ? $this->writeHost['host'] : $this->selectReadHost();
        $dsn = "mysql:host={$host};dbname=your_db;charset=utf8mb4";
        return new PDO($dsn, 'username', 'password');
    }
    /**
     * 判断 SQL 是读还是写
     */
    public function query($sql)
    {
        $trimmed = trim($sql);
        $isWrite = !preg_match('/^(SELECT|SHOW|DESCRIBE|EXPLAIN)/i', $trimmed);
        $conn = $this->getConnection($isWrite);
        return $conn->query($sql);
    }
}

使用数据库中间件 (最推荐)

在实际生产环境中,不推荐在业务代码中配置权重,因为会耦合数据库拓扑,推荐使用中间件:

中间件 权重配置示例
MySQL Proxy read_weight = 3:2:1
MyCat <dataHost balance="1" writeType="0" dbType="mysql"><readHost host="..." weight="3"/></dataHost>
ProxySQL INSERT INTO mysql_servers (hostgroup_id, hostname, port, weight) VALUES (2, 'slave1', 3306, 3);
MaxScale servers = ( slave1, slave2, slave3 ) + weights = 3,2,1
Vitess 通过 VSchema 配置 weight

ProxySQL 配置示例:

-- 添加主机并设置权重
INSERT INTO mysql_servers (hostgroup_id, hostname, port, weight) VALUES 
(2, '192.168.1.1', 3306, 300),
(2, '192.168.1.2', 3306, 200),
(2, '192.168.1.3', 3306, 100);
LOAD MYSQL SERVERS TO RUNTIME;
SAVE MYSQL SERVERS TO DISK;

PHP 代码只需要连接 ProxySQL 一个入口,完全不需要关心权重逻辑。


主从延迟与权重的关系(重要)

权重配置需要结合主从延迟考虑:

  • 延迟高的从库应降低权重(weight 设置小)。
  • 建议采用动态权重,例如根据 SHOW SLAVE STATUSSeconds_Behind_Master 实时调整。
  • 若业务数据一致性要求高,建议 sticky(会话保持)开启,确保写后立即读到新数据。

推荐配置层级

  1. 小型项目(单机 PHP):使用 ThinkPHP 8 内置权重配置(最简单)。
  2. 中型项目(多实例):使用 ProxySQL 中间件统一管理权重。
  3. 大型分布式架构:使用云数据库(如阿里云 PolarDB、腾讯云 TDSQL),它们自带读写分离和权重策略,PHP 只需连接一个入口。

注意事项

  • 权重比例是随机概率,并不是严格轮询。
  • 如果从库宕机,需要健康检查剔除节点,否则会导致部分请求失败。
  • 建议在业务代码层面加上降级策略:当从库全部不可用时,自动切换主库兜底。

抱歉,评论功能暂时关闭!