在 Laravel 中实现数据库读写分离,可以通过以下几种方式来实现:
1. 使用中间件
你可以创建一个中间件来处理读写分离的逻辑。以下是一个简单的示例:
-
创建中间件:
php artisan make:middleware ReadWriteSplitMiddleware
-
在中间件中实现读写分离逻辑:
// app/Http/Middleware/ReadWriteSplitMiddleware.php namespace App\Http\Middleware; use Closure; use Illuminate\Support\Facades\DB; class ReadWriteSplitMiddleware { public function handle($request, Closure $next) { // 假设主数据库连接为 default $readConnection = 'mysql_read'; $writeConnection = 'mysql_write'; // 获取当前请求的表名 $tableName = $request->route('table'); // 根据表名选择读或写连接 if ($tableName && in_array($tableName, config('database.connections.' . $readConnection . '.tables'))) { DB::connection($readConnection)->setAsGlobal(); } else { DB::connection($writeConnection)->setAsGlobal(); } return $next($request); } }
-
注册中间件:
// app/Http/Kernel.php protected $routeMiddleware = [ // 其他中间件 'read_write_split' => \App\Http\Middleware\ReadWriteSplitMiddleware::class, ];
-
在路由中使用中间件:
// routes/web.php Route::middleware(['read_write_split'])->group(function () { Route::get('/read/{table}', function ($table) { // 处理读操作 }); Route::post('/write/{table}', function ($table) { // 处理写操作 }); });
2. 使用数据库连接配置
你可以在 config/database.php
中配置多个数据库连接,并在代码中根据需要选择使用哪个连接。
// config/database.php 'mysql_read' => [ 'driver' => 'mysql', 'host' => env('DB_HOST_READ', '127.0.0.1'), 'port' => env('DB_PORT_READ', '3306'), 'database' => env('DB_DATABASE_READ', 'forge'), 'username' => env('DB_USERNAME_READ', 'forge'), 'password' => env('DB_PASSWORD_READ', ''), 'unix_socket' => env('DB_SOCKET', ''), 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci', 'prefix' => '', 'strict' => true, 'engine' => null, ], 'mysql_write' => [ 'driver' => 'mysql', 'host' => env('DB_HOST_WRITE', '127.0.0.1'), 'port' => env('DB_PORT_WRITE', '3306'), 'database' => env('DB_DATABASE_WRITE', 'forge'), 'username' => env('DB_USERNAME_WRITE', 'forge'), 'password' => env('DB_PASSWORD_WRITE', ''), 'unix_socket' => env('DB_SOCKET', ''), 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci', 'prefix' => '', 'strict' => true, 'engine' => null, ],
然后在代码中根据需要选择使用哪个连接:
// 使用 read 连接 $users = DB::connection('mysql_read')->table('users')->get(); // 使用 write 连接 DB::connection('mysql_write')->table('users')->insert([ 'name' => 'John', 'email' => 'john@example.com', ]);
3. 使用第三方包
你可以使用一些第三方包来实现读写分离,例如 spatie/laravel-read-write-split
。
-
安装包:
composer require spatie/laravel-read-write-split
-
配置包: 发布配置文件:
php artisan vendor:publish --provider="Spatie\ReadWriteSplit\ServiceProvider"
-
在
config/database.php
中配置:// config/database.php 'read' => [ 'driver' => 'mysql', 'host' => env('DB_HOST_READ', '127.0.0.1'), 'port' => env('DB_PORT_READ', '3306'), 'database' => env('DB_DATABASE_READ', 'forge'), 'username' => env('DB_USERNAME_READ', 'forge'), 'password' => env('DB_PASSWORD_READ', ''), 'unix_socket' => env('DB_SOCKET', ''), 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci', 'prefix' => '', 'strict' => true, 'engine' => null, ], 'write' => [ 'driver' => 'mysql', 'host' => env('DB_HOST_WRITE', '127.0.0.1'), 'port' => env('DB_PORT_WRITE', '3306'), 'database' => env('DB_DATABASE_WRITE', 'forge'), 'username' => env('DB_USERNAME_WRITE', 'forge'), 'password' => env('DB_PASSWORD_WRITE', ''), 'unix_socket' => env('DB_SOCKET', ''), 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci', 'prefix' => '', 'strict' => true, 'engine' => null, ],
-
在代码中使用:
// 使用 read 连接 $users = DB::connection('read')->table('users')->get(); // 使用 write 连接 DB::connection('write')->table('users')->insert([ 'name' => 'John', 'email' => 'john@example.com', ]);
通过以上几种方式,你可以在 Laravel 中实现数据库读写分离。选择哪种方式取决于你的具体需求和项目规模。