开始
↓
设计分库分表规则
↓
创建数据库和表结构
↓
实现路由逻辑
↓
执行数据操作
↓
结束
+-------------------+
| 用户请求 |
+-------------------+
↓
+-------------------+
| 路由逻辑 |
+-------------------+
↓
+-------------------+
| 目标数据库/表 |
+-------------------+
↓
+-------------------+
| 数据操作 |
+-------------------+
+-----------------------+
| DatabaseRouter |
+-----------------------+
| + getDatabase() |
| + getTable() |
+-----------------------+
+-----------------------+
| UserRepository |
+-----------------------+
| + create() |
| + find() |
+-----------------------+
Laravel 分库分表
├── 使用场景
│ ├── 高并发系统
│ ├── 大数据存储
│ ├── 分布式架构
│ └── 多租户系统
├── 底层原理
│ ├── 分库
│ ├── 分表
│ ├── 路由
│ └── 聚合
└── 具体步骤
├── 设计规则
├── 创建结构
├── 实现路由
└── 执行操作
以下是一个完整的 Laravel 示例代码,展示如何实现分库分表功能。
在 config/database.php
中配置多个数据库连接:
return [
'connections' => [
'mysql_default' => [
'driver' => 'mysql',
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'default_db'),
'username' => env('DB_USERNAME', 'root'),
'password' => env('DB_PASSWORD', ''),
],
'mysql_shard_1' => [
'driver' => 'mysql',
'host' => env('DB_HOST_SHARD_1', '127.0.0.1'),
'port' => env('DB_PORT_SHARD_1', '3306'),
'database' => env('DB_DATABASE_SHARD_1', 'shard_1_db'),
'username' => env('DB_USERNAME', 'root'),
'password' => env('DB_PASSWORD', ''),
],
'mysql_shard_2' => [
'driver' => 'mysql',
'host' => env('DB_HOST_SHARD_2', '127.0.0.1'),
'port' => env('DB_PORT_SHARD_2', '3306'),
'database' => env('DB_DATABASE_SHARD_2', 'shard_2_db'),
'username' => env('DB_USERNAME', 'root'),
'password' => env('DB_PASSWORD', ''),
],
],
];
注释:
创建一个路由类 DatabaseRouter
,用于动态选择数据库和表:
namespace App\Services;
class DatabaseRouter
{
/**
* 根据用户 ID 获取目标数据库连接
*
* @param int $userId 用户 ID
* @return string 返回数据库连接名称
*/
public static function getDatabase($userId)
{
// 根据用户 ID 的哈希值选择分片数据库
if (crc32($userId) % 2 === 0) {
return 'mysql_shard_1';
} else {
return 'mysql_shard_2';
}
}
/**
* 根据用户 ID 获取目标表名
*
* @param int $userId 用户 ID
* @return string 返回表名
*/
public static function getTable($userId)
{
// 根据用户 ID 的哈希值选择分片表
if (crc32($userId) % 2 === 0) {
return 'users_shard_1';
} else {
return 'users_shard_2';
}
}
}
注释:
getDatabase
方法根据用户 ID 的哈希值选择分片数据库。getTable
方法根据用户 ID 的哈希值选择分片表。创建一个用户仓库类 UserRepository
,用于处理用户数据的增删改查:
namespace App\Repositories;
use App\Services\DatabaseRouter;
use Illuminate\Support\Facades\DB;
class UserRepository
{
/**
* 创建用户记录
*
* @param array $data 用户数据
* @return bool 返回是否创建成功
*/
public function create($data)
{
$userId = $data['id'];
$database = DatabaseRouter::getDatabase($userId); // 获取目标数据库
$table = DatabaseRouter::getTable($userId); // 获取目标表
// 使用 DB Facade 执行插入操作
return DB::connection($database)->table($table)->insert($data);
}
/**
* 查找用户记录
*
* @param int $userId 用户 ID
* @return array 返回用户数据
*/
public function find($userId)
{
$database = DatabaseRouter::getDatabase($userId); // 获取目标数据库
$table = DatabaseRouter::getTable($userId); // 获取目标表
// 使用 DB Facade 执行查询操作
return DB::connection($database)->table($table)->where('id', $userId)->first();
}
}
注释:
create
方法根据用户 ID 动态选择数据库和表,并插入数据。find
方法根据用户 ID 动态选择数据库和表,并查询数据。在控制器中测试分库分表功能:
namespace App\Http\Controllers;
use App\Repositories\UserRepository;
class UserController extends Controller
{
protected $userRepository;
/**
* 构造函数
*
* @param UserRepository $userRepository 用户仓库实例
*/
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
/**
* 创建用户
*
* @return \Illuminate\Http\Response
*/
public function createUser()
{
$data = [
'id' => 1,
'name' => 'Alice',
'email' => '[email protected]',
];
$result = $this->userRepository->create($data); // 调用仓库方法创建用户
return response()->json(['success' => $result]);
}
/**
* 查找用户
*
* @param int $userId 用户 ID
* @return \Illuminate\Http\Response
*/
public function findUser($userId)
{
$user = $this->userRepository->find($userId); // 调用仓库方法查找用户
return response()->json($user);
}
}
注释:
createUser
方法调用仓库类创建用户。findUser
方法调用仓库类查找用户。