middag / chrono-id
支持分片和Doctrine类型的时序ID
Requires
- php: >=7.1
Requires (Dev)
- doctrine/dbal: ^2.8
- friendsofphp/php-cs-fixer: ^2.13
- jms/serializer: ^1.13
- php-mock/php-mock-phpunit: ^2.1
- phpunit/phpunit: ^7.3
- symfony/var-dumper: ^4.1
This package is auto-updated.
Last update: 2020-02-11 18:23:13 UTC
README
ChronoId
是一个时序标识值对象,是自动递增主键的理想替代品。这个库受到 Instagram 在其工程博客上讨论的实现启发:他们的工程博客。
但是,为什么?
我们之前使用 UUID 作为主键,但阅读了这篇文章、这篇文章和这篇文章后,我们决定 UUID 远非理想。或者至少,当与 MySQL 一起使用时。使用有序 UUID 可以帮助解决性能问题,但将二进制数据存储在表中,然后使用权宜之计获取可读 ID 仍然感觉只是权宜之计。
下一个问题:为什么不依赖自增 ID 呢?嗯,我们在项目中使用命令总线,作为这种架构的一部分,我们必须生成 ID 而不 依赖数据库。因此,我们需要像 FancyId::generate()
这样的东西,以尽可能少的依赖关系生成 ID。
解决方案
来看看 ChronoId
!ID 由所谓的 builder 生成。DefaultShardedBuilder
生成由三个组件组成的 ID:时间、分片编号和后缀。每个组件(或块)由给定数量的位组成。DefaultShardedBuilder
生成的 ID 可以整齐地放入 64 位,结构如下
[time][shard][suffix]
根据 time
和 shard
提供者,后缀的长度会增加以增加随机性(因此碰撞尽可能少)。
如果您不需要分片,则 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 位,具体取决于选择的块大小。