caneara / snowflake
创建Twitter Snowflake标识符的包
Requires
- php: ^8.0
- godruoyi/php-snowflake: ^2.0
Requires (Dev)
- orchestra/testbench: ^6.0
- phpunit/phpunit: ^9.0
README
此包允许Laravel应用程序创建Twitter Snowflake标识符。它是Godruoyi创建的出色的Snowflake PHP库的一个非常薄的包装。
什么是Snowflake?
Snowflake是由Twitter设计的一种唯一标识符的形式。在这方面,它们与其他唯一标识符算法(如UUID或ULID)类似。
为什么我应该使用它们?
使用Snowflake(相对于UUID等替代品)的一些好处包括
- 它们完全由整数组成。
- 它们使用更少的空间(16个字符,因此可以适合
BIGINT
)。 - 整数索引比字符串索引快得多。
- 键以时间戳开始,因此是可排序的。
- 键以随机数结束,因此无法猜测表大小。
- 数据库比字符串更有效地处理整数。
- 生成新键的速度更快(小于1毫秒)。
安装
使用Composer引入包
composer require caneara/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
方法来生成Snowflake。
resolve('snowflake')->id(); // (string) "5585066784854016"
警告:不要创建Snowflake服务的实例,因为这可能导致生成匹配的键/引入冲突。相反,始终从容器中解析Snowflake单例。您还可以使用全局辅助方法(见下文)。
由于这有点麻烦,因此该包还注册了一个全局的snowflake()
辅助方法,您可以在任何地方使用。
snowflake(); // (string) "5585066784854016"
数据库
如果您想在数据库中使用Snowflakes,例如用于主键和外键,那么您需要执行几个步骤。
首先,修改您的迁移,以便它们使用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
对所有Snowflake属性进行转换。此转换在从数据库存储或检索Snowflake时自动处理从string
到integer
以及反向转换。它还确保不支持64位整数(如JavaScript)的语言不会截断Snowflake。
<?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,但如果它们本质上是重大的,请确保还包括测试或测试。
许可
MIT许可(MIT)。请参阅许可文件获取更多信息。