PHP读写分离在Laravel中怎么配

wen PHP项目 1

本文目录导读:

PHP读写分离在Laravel中怎么配

  1. 基础配置(config/database.php)
  2. 完整配置示例(带多个从库)
  3. 使用不同数据库名称的配置
  4. 验证读写分离
  5. 使用.env配置(推荐)
  6. 注意事项
  7. 查看当前使用的连接

在Laravel中配置MySQL读写分离非常简单,主要通过修改 config/database.php 实现,以下是完整配置方案:

基础配置(config/database.php)

'mysql' => [
    'read' => [
        'host' => [
            '192.168.1.101', // 从库1
            '192.168.1.102', // 从库2(可选)
        ],
    ],
    'write' => [
        'host' => [
            '192.168.1.100', // 主库
        ],
    ],
    'sticky'    => true, // 读写粘性(可选)
    'driver'    => 'mysql',
    'database'  => 'your_database',
    'username'  => 'your_username',
    'password'  => 'your_password',
    'charset'   => 'utf8mb4',
    'collation' => 'utf8mb4_unicode_ci',
    'prefix'    => '',
],

完整配置示例(带多个从库)

'mysql' => [
    // 读取(从库)配置
    'read' => [
        'host' => [
            '192.168.1.101',
            '192.168.1.102',
            '192.168.1.103',
        ],
        'port' => 3306,
    ],
    // 写入(主库)配置
    'write' => [
        'host' => [
            '192.168.1.100',
        ],
        'port' => 3306,
    ],
    // 公共配置(读写共享)
    'driver'    => 'mysql',
    'database'  => 'laravel_db',
    'username'  => 'app_user',
    'password'  => 'secure_password',
    'charset'   => 'utf8mb4',
    'collation' => 'utf8mb4_unicode_ci',
    // 连接池和粘性设置
    'sticky'    => true,  // 同一请求内写入后读取使用主库
    'prefix'    => '',
    // 高级配置
    'options' => [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        PDO::ATTR_EMULATE_PREPARES => false,
    ],
],

使用不同数据库名称的配置

如果主从库数据库名不同:

'read' => [
    'host' => ['192.168.1.101'],
    'database' => 'read_db', // 从库数据库名
],
'write' => [
    'host' => ['192.168.1.100'],
    'database' => 'write_db', // 主库数据库名
],

验证读写分离

// 在控制器或服务中测试
public function testReadWrite()
{
    // 写入操作(会连接主库)
    $user = new User();
    $user->name = '测试用户';
    $user->save();
    // 读取操作(会连接从库)
    $users = User::all();
    // 查看实际连接的数据库
    \DB::enableQueryLog();
    User::find(1);
    $queries = \DB::getQueryLog();
    dd($queries); // 可以看到具体连接的数据库
}

使用.env配置(推荐)

# .env 文件
DB_HOST_MASTER=192.168.1.100
DB_HOST_SLAVE_1=192.168.1.101
DB_HOST_SLAVE_2=192.168.1.102
DB_DATABASE=laravel_db
DB_USERNAME=app_user
DB_PASSWORD=secret

然后在 config/database.php 中:

'read' => [
    'host' => [
        env('DB_HOST_SLAVE_1'),
        env('DB_HOST_SLAVE_2'),
    ],
],
'write' => [
    'host' => [
        env('DB_HOST_MASTER'),
    ],
],

注意事项

  1. sticky 选项:设为 true 时,同一请求中写入后立即读取会使用主库,避免数据不一致

  2. 负载均衡:Laravel 会随机选择从库进行读取,实现简单的负载均衡

  3. 读写分离不适用于事务:在事务中所有操作都会使用主库

\DB::transaction(function () {
    // 事务内所有操作都在主库执行
    User::create([...]);
    $user = User::find(1); // 这里也是主库
});
  1. 强制使用主库读取
User::onWriteConnection()->find(1); // 强制使用主库
  1. 指定连接
$users = DB::connection('mysql')->table('users')->get(); // 使用默认连接

查看当前使用的连接

// 查看当前连接配置
$connection = DB::connection();
dd($connection->getConfig());
// 查看执行的SQL及连接的数据库
\DB::listen(function ($query) {
    dump($query->sql);
    dump($query->connection->getDatabaseName());
});

通过以上配置,Laravel 会自动处理读写分离,无需手动干预。

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