在 Laravel 中实现数据库读写分离,可以通过以下几种方式来实现:
你可以创建一个中间件来处理读写分离的逻辑。以下是一个简单的示例:
创建中间件:
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) {
// 处理写操作
});
});
你可以在 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',
]);
你可以使用一些第三方包来实现读写分离,例如 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 中实现数据库读写分离。选择哪种方式取决于你的具体需求和项目规模。