glhd / bits
Requires
- php: ^8.1
- ext-json: *
- illuminate/contracts: ^9|^10|^11|12.x-dev|dev-master
- illuminate/support: ^9|^10|^11|12.x-dev|dev-master
- nesbot/carbon: ^2.62.1|^3.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.5
- orchestra/testbench: ^7.10|^8|^9|9.x-dev|10.x-dev|dev-master
- spatie/laravel-ray: ^1.32
This package is auto-updated.
Last update: 2024-09-21 04:50:42 UTC
README
Bits
Bits是一个用于在分布式计算中生成唯一64位标识符的PHP库。您可以使用Bits创建Twitter Snowflake IDs、Sonyflake IDs或任何其他使用位序列的唯一ID。
安装
composer require glhd/bits
配置
警告
如果您没有配置工作ID和数据中心ID,您可能会在多个应用服务器上使用Bits时遇到并发问题。
您需要配置以下两项以确保您的ID有效且唯一。
设置BITS_WORKER_ID
和BITS_DATACENTER_ID
由于每个工作都有自己的ID,雪花ID非常紧凑。如果您在多个数据中心运行多个服务器,您需要为每个数据中心分配一个唯一的值。您需要为应用程序使用的每个数据中心设置唯一的BITS_DATACENTER_ID
(0-31),同一数据中心中的每个工作应具有唯一的BITS_WORKER_ID
(0-31)。这意味着您最多可以有1024个不同的工作在同一时间生成雪花。
注意
如果您使用Lambda,这可能会成为一个问题。我们最终希望为Bits提供一个无服务器解决方案,但目前如果您在Laravel Vapor之类的环境中生成雪花,您需要自行管理锁定/释放ID。
设置BITS_EPOCH
雪花ID紧凑的另一个原因是它们使用自定义的“epoch”值(而不是1970年1月1日的Unix纪元)。这是可以生成雪花的最早时间,也设置了雪花可以生成的未来时间的限制。默认值为2023-01-01
,对于大多数系统来说应该是足够的。但如果您在测试中要使用时间旅行回到2023年1月之前,这可能会引起问题(在这种情况下,您应该将epoch设置在您将时间旅行到的时间之前)。
使用方法
要获取新的雪花ID,只需调用Snowflake::make()
。这将返回一个新的Snowflake对象
class Snowflake { public readonly int $timestamp; public readonly int $datacenter_id; public readonly int $worker_id; public readonly int $sequence; public function id(): int; public function is(Snowflake $other): bool; }
如果您更喜欢,也可以使用全局辅助函数snowflake()
或sonyflake()
。
所有Bits ID都实现了__toString()
和Laravel Query\Expression
接口,这样您就可以轻松地传递它们而不用担心类型。
与JavaScript一起使用
请注意,JavaScript只支持~52位整数,因此如果您将雪花传递到JavaScript中,请确保将它们转换为字符串。
所有Bits ID都实现了Jsonable
和JsonSerializable
,因此如果您将Bits实例传递给json_encode
,它将自动为您处理。但如果您使用由Bits生成的整数ID,您将必须自己转换它们。
与Eloquent模型一起使用
Bits提供了Eloquent的HasUuids
和HasUlids
特性相同行为的HasSnowflakes
特性。只需将HasSnowflakes
添加到您的模型中,当它们被插入或更新时,就会为您生成一个新的雪花。
您还可以在Eloquent的$casts
数组中使用Snowflake
或Sonyflake
,以使该属性自动转换为Bits实例。
use Glhd\Bits\Database\HasSnowflakes; use Glhd\Bits\Snowflake; use Illuminate\Database\Eloquent\Model; class Example extends Model { // Auto-generate Snowflake for new models use HasSnowflakes; // Any attribute can be cast to a `Snowflake` (or `Sonyflake`) protected $casts = [ 'id' => Snowflake::class, ]; } $example = Example::create(); $example->id instanceof Snowflake; // true echo $example->id; // 65898467809951744
使用ID作为时间戳
雪花和Sonyflake的一个优点是它们可以根据时间排序,并且可以从ID中提取时间戳供以后使用。这意味着如果您愿意,可以使用这些ID代替created_at
时间戳。
// Instead of: User::where('created_at', '>', now()); // You can do (assuming users.id is a snowflake) User::where('id', '>', app(MakesSnowflakes::class)->firstForTimestamp(now()));
// Instead of: $created_at = $user->created_at; // You can do (assuming User::id is cast to a Snowflake object) $created_at = $user->id->toCarbon();
与Livewire一起使用
如果您使用Livewire,可以使用SnowflakeSynth
合成器使雪花在您的组件中可用。
您只需要在AppServiceProvider
中注册合成器。
use Glhd\Bits\Support\Livewire\SnowflakeSynth; use Glhd\Bits\Support\Livewire\BitsSynth; class AppServiceProvider extends ServiceProvider { public function boot(): void { // If only using Snowflakes: Livewire::propertySynthesizer(SnowflakeSynth::class); // If using Sonyflakes or a custom Bits variant: Livewire::propertySynthesizer(BitsSynth::class); } }
如果您使用非Snowflake版本的Bits,可以使用BitsSynth
,它支持Bits的任何版本,但代价是存储更多的数据。
关于64位唯一ID
雪花格式
0 0000001100100101110101100110111100101011 01011 01111 000000011101
┳ ━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━ ━━━┳━ ━┳━━━ ━┳━━━━━━━━━━
┗━ unused bit ┗━ timestamp (41) ┃ ┃ ┗━ sequence (12)
datacenter (5) ━┛ ┗━ worker (5)
Sonyflake格式
0 000000011001001011101011001101111001010 11010110 1111000000011101
┳ ━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━┳━ ━┳━━━━━━━━━━━━━━
┗━ sign ┗ timestamp (39) sequence (8) ┛ ┗ machine (16)
这两个ID都由相同的64位整数56705782302306333
表示,但传达了不同的元数据。根据您的规模和分布需求,您可能发现其中一个或另一个格式更合适,或者选择实现您自己的自定义格式。
Bits可以生成您想要的任何类型的64位唯一ID,以最适合您用例的方式。