morozmkhl/scalable-db 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

morozmkhl/scalable-db

Composer 安装命令:

composer require morozmkhl/scalable-db

包简介

Advanced sharding, replication & fail‑over package for Laravel 11

README 文档

README

Shard routing layer for Laravel 11 applications. The package resolves a tenant or entity key to a database shard, switches the default connection for the duration of a callback or HTTP request, and provides optional fail-over and operational CLI commands.

Tests

Requirements

Component Version
PHP ^8.2
Laravel ^11.5

Installation

composer require morozmkhl/scalable-db
php artisan vendor:publish --tag=scalable-db-config

Optional publish targets:

php artisan vendor:publish --tag=scalable-db-migrations
php artisan vendor:publish --tag=scalable-db-database

The scalable-db-database tag provides a sample database-shards.php stub with read/write host configuration.

Configuration

Publish config/scalable-db.php and define shard connections in config/database.php. Each shard entry maps a logical name to a Laravel connection name and an optional list of replica connections used during fail-over.

return [
    'default_strategy' => 'hash',

    'strategies' => [
        'hash' => [
            'shard_count' => 2,
            'map' => [0 => 'shard_0', 1 => 'shard_1'],
        ],
    ],

    'shards' => [
        'shard_0' => [
            'connection' => 'shard0_master',
            'replicas' => ['shard0_replica1'],
        ],
        'shard_1' => [
            'connection' => 'shard1_master',
            'replicas' => [],
        ],
    ],

    'failover' => [
        'auto_failover' => false,
        'max_retries' => 1,
        'fallback_connection' => null,
    ],
];

Fail-over is disabled by default. Set auto_failover to true to enable replica retry on PDOException.

Further reference: Configuration.

Sharding strategies

Hash

Assigns keys using crc32((string) $key) % shard_count and a slot-to-shard map.

'strategies' => [
    'hash' => [
        'shard_count' => 2,
        'map' => [0 => 'shard_0', 1 => 'shard_1'],
    ],
],
'default_strategy' => 'hash',
use ScalableDB\Facades\Shard;

Shard::forTenant($userId)->run(function () use ($userId) {
    return User::find($userId);
});

Range

Assigns keys by inclusive numeric ranges.

'strategies' => [
    'range' => [
        'ranges' => [
            ['min' => 1,     'max' => 10000,  'shard' => 'shard_0'],
            ['min' => 10001, 'max' => 20000,  'shard' => 'shard_1'],
        ],
    ],
],
'default_strategy' => 'range',
Shard::forTenant($orderId)->run(function () use ($orderId) {
    return Order::find($orderId);
});

Lookup

Resolves keys from a lookup table (for example, tenants). Supports optional query result caching.

'strategies' => [
    'lookup' => [
        'connection'   => 'lookup',
        'table'        => 'tenants',
        'key_column'   => 'id',
        'shard_column' => 'shard',
        'cache_ttl'    => 300,
    ],
],
'default_strategy' => 'lookup',
Shard::forTenant($tenantId)->run(function () use ($tenantId) {
    return Post::where('tenant_id', $tenantId)->get();
});

Strategy details: Sharding strategies.

Read/write splitting

ScalableDB does not implement read/write routing. Configure read, write, and sticky on each shard connection in config/database.php using Laravel's built-in behaviour. The package switches the default connection to the shard master; Laravel routes individual statements to read or write hosts within that connection.

'shard0_master' => [
    'driver' => 'mysql',
    'read'   => ['host' => ['replica1.example.com']],
    'write'  => ['host' => ['master.example.com']],
    'sticky' => true,
],

Optional helpers select the read or write PDO for the current connection:

Shard::forTenant($id)->forRead()->run(fn () => User::find($id));
Shard::forTenant($id)->forWrite()->run(fn () => User::create([...]));

HTTP middleware

Register routes behind the shard.tenant middleware alias. The middleware resolves a tenant identifier in the following order:

  1. $request->user()->tenant_id, or $request->user()->id when tenant_id is absent
  2. HTTP header X-Tenant-ID
  3. Query parameter tenant_id

If no tenant identifier is present, the request proceeds without changing the active shard.

Route::middleware('shard.tenant')->group(function () {
    Route::get('/posts', [PostController::class, 'index']);
});

Artisan commands

Command Description
php artisan shard:migrate [--shard=NAME] [--path=PATH] Run migrations on all shards or one shard
php artisan shard:seed Run the configured seeder class
php artisan shard:status Report connectivity for masters and replicas
php artisan shard:diagnose [--json] Full diagnostics; exit code 1 on failure

Command reference: CLI.

Events

Event Dispatched when
ShardResolved A shard name is resolved from a tenant key
ShardFailover Fail-over switches from master to a replica or fallback connection
use ScalableDB\Events\ShardFailover;
use Illuminate\Support\Facades\Event;

Event::listen(ShardFailover::class, function (ShardFailover $event) {
    logger()->warning("Fail-over {$event->shard}: {$event->fromConnection} -> {$event->toConnection}", [
        'error' => $event->exception->getMessage(),
    ]);
});

Telescope

Laravel Telescope is an optional dependency. When present, the package registers a watcher that tags entries with shard:<name> based on the active shard context.

Testing

composer test
composer lint -- --test
composer analyse

The test suite uses Pest and Orchestra Testbench. CI runs lint, static analysis, a PHP 8.2/8.4 × SQLite/MySQL matrix, and a Docker demo smoke test.

Demo environment

A Docker-based demo application is provided under demo/.

cd demo
docker compose up -d --build
curl http://localhost:8000/ping
curl -X POST -d "id=5&name=Eve" http://localhost:8000/users
curl http://localhost:8000/users/shard/5

See Demo.

Limitations

  • Single-shard scope. Queries run against one shard per callback or request. Cross-shard joins, aggregates, and transactions are not supported.
  • Fail-over trigger. Fail-over reacts to PDOException only. Application-level errors and connection timeouts outside PDO are not handled automatically.
  • Fail-over default. auto_failover is false by default; replica retry must be enabled explicitly.
  • Replica writes. Fail-over may route traffic to a read-only replica. Write operations against a replica can fail at the database level.
  • No rebalancing. The package does not migrate data between shards or rebalance keys.
  • No distributed transactions. Two-phase commit and saga patterns are out of scope.
  • Replication setup. MySQL (or other) replication must be configured manually in config/database.php.
  • Strategy binding. ShardManager is registered as a singleton. Changing default_strategy at runtime requires app()->forgetInstance('shard.manager').

Documentation

Full documentation is in docs/: installation, configuration, architecture, API, CLI, and development notes.

Contributing

Run the following before opening a pull request:

composer lint -- --test
composer analyse
composer test

Code style is enforced with Laravel Pint. Static analysis uses PHPStan with Larastan.

License

The MIT License. See LICENSE.

统计信息

  • 总下载量: 0
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 3
  • 点击次数: 0
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 3
  • Watchers: 1
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-07-11

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固