calebdw/laraflake

一个用于创建 X/Twitter Snowflake 标识符的 Laravel 扩展包。

v1.1.0 2024-08-02 03:52 UTC

This package is auto-updated.

Last update: 2024-09-02 04:06:17 UTC


README

Laraflake

在 Laravel 中生成 X/Twitter Snowflake 标识符

Test Results Code Coverage License Packagist Version Total Downloads

什么是 Snowflake?

Snowflake 是由 X/Twitter 设计的一种唯一标识符,许多公司,包括 Instagram 和 Discord,使用它来为其实体生成唯一 ID。

使用 Snowflake(与 UUID/ULID 等替代品相比)的一些优点包括

  • 时间戳组件:直接从 ID 中提取创建时间。
  • 跨分布式系统唯一性:确保唯一 ID 而无需协调。
  • 可排序性:大致按创建时间排序,便于排序。
  • 紧凑性:64 位大小,比 128 位 UUID 更紧凑。
  • 性能:生成速度快,资源消耗少。
  • 可配置性:灵活的位分配,以满足特定需求。
  • 存储效率:与更大的标识符相比,存储效率更高。
  • 数据库索引:更快的索引和查询性能。
  • 人类可读性:比更长标识符更紧凑、更易读。

安装

首先使用 Composer 拉取包

composer require calebdw/laraflake

然后发布包的配置文件

php artisan vendor:publish --provider="CalebDW\Laraflake\ServiceProvider"

配置

Snowflake 类型

Snowflake 类型决定了用于生成 Snowflakes 的类。

默认的 Snowflake 类型是 Godruoyi\Snowflake\Snowflake,它使用 41 位用于纪元,5 位用于数据中心 ID,5 位用于工作 ID,以及 12 位用于序列。这允许每个工作最多有 1024 个工作节点,并且每个工作节点每毫秒可以有 4096 个唯一 ID。

您可以将 Snowflake 类型更改为 Godruoyi\Snowflake\Sonyflake,它使用 39 位用于纪元,16 位用于机器 ID,以及 8 位用于序列。这允许每 10 毫秒 每个工作节点最多有 65535 台机器和 256 个唯一 ID。

纪元

编码在 Snowflake 中的时间戳是创建时间与给定起始纪元/时间戳之间的差异。Snowflakes 使用 41 位,可以生成给定纪元之后最多 69 年的 ID。Sonyflakes 使用 39 位,可以生成给定纪元之后最多 174 年的 ID。

在大多数情况下,您应该使用 YYYY-MM-DD 格式将其设置为当前日期。

注意:未来的日期将引发错误,您应该避免使用遥远的过去(如 Unix 纪元 1970-01-01)的日期,因为这可能会减少您可以生成的时间戳的年数。

数据中心 ID 与工作 ID

注意:这仅用于 Snowflake 类型。

您可以为生成 Snowflakes 时应用程序应使用的数据中心 ID 和工作 ID 进行设置。这些用于确保每个工作节点生成唯一的 Snowflakes,其值范围从 031(最多 1024 个唯一工作节点)。

机器 ID

注意:这仅用于 Sonyflake 类型。

您可以为生成Sonyflakes时应用程序应使用的机器ID进行设置。这用于确保每台机器生成的Sonyflakes是唯一的,范围从 065535

用法

警告:不要创建新的Snowflake生成器实例(因为这可能导致冲突),始终使用容器中的Snowflake单例。

您可以通过从容器解析单例并调用其id方法来生成Snowflake

use Godruoyi\Snowflake\Snowflake;

resolve('snowflake')->id();      // (string) "5585066784854016"
resolve(Snowflake::class)->id(); // (string) "5585066784854016"

此包还提供了一个snowflake辅助函数、一个Snowflake外观类以及一个Str::snowflakeId宏,以便更方便地使用

use CalebDW\Laraflake\Facades\Snowflake;
use Illuminate\Support\Str;

snowflake()->id();  // (string) "5585066784854016"
Snowflake::id();    // (string) "5585066784854016"
Str::snowflakeId(); // (string) "5585066784854016"

Eloquent集成

迁移

此包提供了一系列迁移宏,以便更容易地在数据库模式中使用Snowflakes。

以下是一个示例

return new class extends Migration
{
    public function up(): void
    {
        Schema::create('comments', function(Blueprint $table) {
            $table->snowflake()->primary();
            $table->foreignSnowflake('user_id')->constrained()->cascadeOnDelete();
            $table->foreignSnowflakeFor(Post::class)->constrained();
        });
    }
}

模型

接下来,将包的HasSnowflakes特质添加到您的Eloquent模型中

namespace App\Models;

use CalebDW\Laraflake\Concerns\HasSnowflakes;

class Post extends Model
{
    use HasSnowflakes;
}

该特质为模型提供了几个Snowflake列的功能

  • 为新记录生成Snowflakes
  • 路由模型绑定
  • 自动将数据库整数转换为字符串,防止在不支持64位整数(如JavaScript)的语言中截断。

默认情况下,该特质假定模型的主键是Snowflake。如果您有其他应视为Snowflakes的唯一列,则可以覆盖uniqueIds方法来指定它们

namespace App\Models;

use CalebDW\Laraflake\Concerns\HasSnowflakes;

class Post extends Model
{
    use HasSnowflakes;

    /** @inheritDoc */
    public function uniqueIds(): array
    {
        return [$this->getKeyName(), 'slug'];
    }
}

如有必要,您可以使用AsSnowflake类型转换显式地将模型的Snowflake列转换为Snowflake

namespace App\Models;

use CalebDW\Laraflake\Casts\AsSnowflake;
use CalebDW\Laraflake\Concerns\HasSnowflakes;

class Post extends Model
{
    use HasSnowflakes;

    protected $casts = [
        'id'      => AsSnowflake::class,
        'user_id' => AsSnowflake::class,
    ];
}

验证

如果您需要在应用程序中验证Snowflakes,可以使用此包提供的Snowflake规则或Rule::snowflake

use CalebDW\Laraflake\Rules\Snowflake;
use Illuminate\Validation\Rule;

$request->validate([
    'id'      => ['required', new Snowflake()],
    'user_id' => ['required', Rule::snowflake()],
]);

您也可以仅使用Str::isSnowflake宏来检查一个值是否是有效的Snowflake

use Illuminate\Support\Str;

Str::isSnowflake('5585066784854016'); // (bool) true

序列解析器

序列解析器负责生成Snowflake的序列组件,以确保在同一毫秒内同一台机器生成的数字是唯一的。

默认情况下,如果应用程序有缓存,则使用LaravelSequenceResolver,该解析器使用Laravel缓存来存储最后一个序列号。如果没有缓存,则使用没有依赖项但不是线程安全的RandomSequenceResolver

您可以通过在服务提供器中绑定自己的实现来覆盖序列解析器

use Godruoyi\Snowflake\SequenceResolver;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        $this->app->bind(SequenceResolver::class, function() {
            return new MySequenceResolver();
        });
    }
}

有关可用的序列解析器和它们的依赖项的更多信息,请参阅godruoyi/php-snowflake

贡献

感谢您考虑贡献!您可以在此处阅读贡献指南。

许可证

Laraflake是开源软件,许可协议为MIT许可证

致谢

源自caneara/snowflake,该库已不再维护。实际的Snowflake生成由优秀的godruoyi/php-snowflake库处理。

替代方案