middag/chrono-id

支持分片和Doctrine类型的时序ID

1.1.1 2019-01-11 15:00 UTC

This package is auto-updated.

Last update: 2020-02-11 18:23:13 UTC


README

Travis (.org) Packagist

ChronoId 是一个时序标识值对象,是自动递增主键的理想替代品。这个库受到 Instagram 在其工程博客上讨论的实现启发:他们的工程博客

但是,为什么?

我们之前使用 UUID 作为主键,但阅读了这篇文章这篇文章这篇文章后,我们决定 UUID 远非理想。或者至少,当与 MySQL 一起使用时。使用有序 UUID 可以帮助解决性能问题,但将二进制数据存储在表中,然后使用权宜之计获取可读 ID 仍然感觉只是权宜之计。

下一个问题:为什么不依赖自增 ID 呢?嗯,我们在项目中使用命令总线,作为这种架构的一部分,我们必须生成 ID 而不 依赖数据库。因此,我们需要像 FancyId::generate() 这样的东西,以尽可能少的依赖关系生成 ID。

解决方案

来看看 ChronoId!ID 由所谓的 builder 生成。DefaultShardedBuilder 生成由三个组件组成的 ID:时间、分片编号和后缀。每个组件(或块)由给定数量的位组成。DefaultShardedBuilder 生成的 ID 可以整齐地放入 64 位,结构如下

[time][shard][suffix]

根据 timeshard 提供者,后缀的长度会增加以增加随机性(因此碰撞尽可能少)。

如果您不需要分片,则 DefaultUnshardedBuilder 就足够好了,并且还可以节省一些存储空间。

安装

composer require middag/chrono-id

使用

use MIDDAG\ChronoId\Builder\DefaultShardedBuilder;
use MIDDAG\ChronoId\ChronoId;

$builder = DefaultShardedBuilder::factory();

// Optional: this is done automatically by the builder
ChronoId::setBuilder($builder);

// Generate an ID
$chronoId = ChronoId::generate();

print $chronoId->getInteger();

// -> 21791542821782533

高级

待办事项

块大小

TimeProvider 对最终 ID 的大小影响最大。UnixEpochTimeProvider 需要 45 位来存储具有适当精度的时间戳(以避免碰撞),而 CustomEpochTimeProvider 仅需要 41 到 45 位,具体取决于选择的块大小。