itransport/snowflake

用于创建Twitter Snowflake标识符的包

1.0.0 2022-06-03 08:55 UTC

This package is not auto-updated.

Last update: 2024-09-21 18:30:49 UTC


README

此包使Laravel应用能够创建Twitter Snowflake标识符。它是对Godruoyi创建的优秀Snowflake PHP库的一个非常薄的包装。

什么是Snowflake?

Snowflake是Twitter设计的一种唯一标识符。在这方面,它们与其他唯一标识符算法(如UUID或ULID)类似。

为什么我应该使用它们?

我写了一篇文章,探讨了Snowflake相对于其他唯一标识符的优点。然而,简而言之

  • 它们完全由整数组成。
  • 它们使用更少的空间(16个字符,所以它适合在BIGINT中)。
  • 整数索引比字符串索引快得多。
  • 键以时间戳开头,因此是可排序的。
  • 键以随机数结尾,因此无法猜测表的大小。
  • 数据库比字符串更有效地处理整数。
  • 生成新键更快(小于1毫秒)。

安装

使用Composer拉入包

composer require itransport/snowflake

配置

Snowflake包含一个配置文件,其中包含几个设置,您可以使用这些设置初始化Snowflake服务。您应该首先发布此配置文件

php artisan vendor:publish

分布式架构

此服务允许使用涉及数据中心和工作节点(每个节点都负责根据其指定的标识符生成Snowflake)的分布式架构设置。为了最大灵活性以及向后兼容性,这是默认配置。

如果您不打算运行分布式架构设置,那么您的第一步应该是将相应的配置值设置为false

数据中心和工作节点

当使用分布式架构设置时,您需要设置应用程序在生成Snowflake时应使用的数据中心和工作节点。这两个值默认都设置为1,这是一个很好的起点,但您可以根据需要增加这些数字,以添加更多中心节点。

这些配置值的最大值是31。这为您提供了每个数据中心多达31个节点,总共31个数据中心。因此,您可以拥有多达961个工作节点,每个节点都生成唯一的Snowflake。

如果您已禁用分布式架构,则可以跳过数据中心和工作节点值,因为服务将忽略这些值。

起始时间戳

服务在生成唯一Snowflake的过程中将Unix纪元与给定的起始时间戳进行比较。因此,可以使用任何给定的起始时间戳生成长达69年的Snowflake。

在大多数情况下,您应将此值设置为当前日期,格式为YYYY-MM-DD

不要将时间戳设置为未来的日期,因为这不会产生任何效果。您还应避免使用过去的日期,因为这可能会减少您可以生成的时间戳的年份。

序列解析器

为了处理同一毫秒内唯一键的生成,服务使用序列解析器。有几种可供选择,但它们各自都有依赖项,例如Redis。您可以使用任何一种,但是默认选项是一个很好的选择,因为它没有任何依赖项

使用方法

您可以通过将服务从容器中解析出来并调用其 id 方法来生成一个雪花。

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

警告:请不要创建 Snowflake 服务的实例,这样做可能会导致生成匹配的键或引入冲突。相反,始终从容器中解析 Snowflake 单例。您还可以使用全局帮助方法(见下文)。

由于这有点繁琐,因此该包还注册了一个全局的 snowflake() 帮助方法,您可以在任何地方使用它。

snowflake(); // (string) "5585066784854016"

数据库

如果您想在数据库中使用雪花(例如,作为主键和外键),则需要执行几个步骤。

首先,修改您的迁移,使其使用 Snowflake 迁移方法,例如。

// Before
$table->id();
$table->foreignId('user_id');
$table->foreignIdFor(User::class);

// After
$table->snowflake()->primary();
$table->foreignSnowflake('user_id');
$table->foreignSnowflakeFor(User::class);

下面是一个示例

class CreatePostsTable extends Migration
{
    public function up()
    {
        Schema::create('posts', function(Blueprint $table) {
            $table->snowflake()->primary();
            $table->foreignSnowflake('user_id')->constrained()->cascadeOnDelete();
            $table->string('title', 100);
            $table->timestamps();
        });
    }
}

接下来,如果您正在使用 Eloquent,请将包的 Snowflakes 特性添加到您的 Eloquent 模型中。

<?php

namespace App\Models;

use Snowflake\Snowflakes;

class Post extends Model
{
    use Snowflakes;
}

最后,配置模型的 $casts 数组以使用包的 SnowflakeCast 对所有雪花属性进行转换。这种转换在将雪花存储到数据库或从数据库获取雪花时自动处理从 stringinteger 以及反之的转换。它还确保不支持 64 位整数的语言(例如 JavaScript)不会截断雪花。

<?php

namespace App\Models;

use Snowflake\Snowflakes;
use Snowflake\SnowflakeCast;

class Post extends Model
{
    use Snowflakes;

    protected $casts = [
        'id'      => SnowflakeCast::class,
        'user_id' => SnowflakeCast::class,
        'title'   => 'string',
    ];
}

贡献

感谢您考虑为 Snowflake 做出贡献。欢迎您提交包含改进的 PR,但如果它们本质上是重大的,请确保还包括测试或测试。

支持项目

如果您想支持 Snowflake 的发展,请考虑赞助我。非常感谢!

许可证

MIT 许可证(MIT)。有关更多信息,请参阅许可证文件