charm/uuid

一个非常快速且无依赖的库,用于生成UUID(GUID)版本1或4,可排序的UUID且验证通过,或者根据Twitter的Snowflake、Sonyflake或Instaflake算法生成的64位唯一标识符。

0.0.6 2021-08-04 18:03 UTC

This package is auto-updated.

Last update: 2024-09-19 11:04:20 UTC


README

在查看其他库之后,它们对于最常见的用例(生成UUID)来说似乎非常复杂。现在,UUID本身已经很复杂,很容易出错,导致UUID不是真正的唯一。这就是为什么我认为库应该尽可能简单,以便于审查。

特性

  • 使用密码学强随机性生成UUID v4

  • UUID v1

  • COMB UUID v4 - 所有新的UUID都将大于之前的UUID。UUID由60位时间戳、14位序列号和48位机器ID构建。在本实现中,UUID将验证为有效的UUID v4,这意味着任何挑剔的第三方软件在验证UUID时都将将其视为符合版本4 UUID。

  • Snowflake UID - 适用于数据库主键的64位递增ID

  • Instaflake UID - Snowflake UID的变体

  • Sonyflake UID - Snowflake的另一种变体

此库提供两个类,无依赖,性能良好。UUID v4是密码学随机(通过random_bytes()),而UUID v1试图找到MAC地址或其他唯一机器ID。为了减少冲突的风险,使用进程ID以减少单个机器生成两个相同ID的机会。

基准测试

第一个UUID的生成速度几乎与原生的PECL扩展相同

[编辑](https://quickchart.io/chart-maker/edit/zm-ba284464-1ba4-4795-a7e8-dcf8f00d1e71)

对于许多UUID,速度比原生的PECL扩展更快。

[编辑](https://quickchart.io/chart-maker/edit/zm-42160b97-4a31-4a17-b591-98676a688b09)

摘要

请参阅BENCHMARKS.md文件以获取详细信息。值得注意的是

  1. 生成第一个UUID少于1毫秒,比ramsey/uuid的UUID v1快10.5毫秒,比UUID v4快3.9毫秒。
  2. 开销与加载源文件有关。

这些UUID是否真正唯一?

UUID(4)

此库生成的随机UUID(4)是工业级的,直接使用操作系统通过random_bytes()函数提供的熵。

UUID(1)

考虑到在其他库中的错误报告和经验,实现了基于时间和位置UUID(1)算法。可能出现的问题与进程的分支有关,构建字节的算法是RFC 4122附录A中提供的C代码的精确移植。

然而,PHP中的microtime(true)函数的时间分辨率不够准确,

UUID标准的定义投入了大量努力,并且在实际应用中被认为是唯一的。

UUID v4是最容易使用的,但每个UUID需要16字节存储空间。它们无需配置,并且可以非常快速地生成。如果世界上所有公司在每秒生成10亿个UID,第一个碰撞预计将在大约85年后发生。在那些85年后,这些UUID中的大多数无论如何都会消失。

Snowflake ID只有8字节(64位),可以安全地用于您自己的数据库中。它是Twitter发明的,用于生成推文、用户、事物、图片等的唯一ID。为了确保唯一性,您可以配置一个唯一的machineId,但如果您不这样做,库将自动从操作系统中选择一个可用的machine id。

UUID v1是一个使用时钟和从MAC地址或其他唯一48位机器标识符派生的唯一机器ID的“坐标”。在此库中,它们也是自动配置的。

警告

请在使用此库之前在自己的环境中运行一些测试。特别是,如果您使用UUID版本4,请确保服务器有足够的熵。熵是从网络噪音和其他来源生成的随机数。

UUID版本4被认为是生产就绪的,但其他ID在我们可以宣布它们为生产就绪之前需要更多的审查。如果您发现任何问题,请让我知道。

快速入门

如果您不使用服务容器,最快开始的方式是使用Charm\Id::make()函数。返回的值将是一个加密随机128位值,以UUID v4形式(XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX)表示。

安装

与其他大多数PHP包一样,安装composer并运行

# composer require charm/uuid

或者您当然可以克隆https://github.com/charm-php/uuid上的存储库,并包含我们提供的./autoload.php文件。

UUID v4

这是最快、最容易使用的,因为它没有任何配置选项。碰撞的概率微乎其微。不同组合的数量约为5,3169e+36。

如果发生碰撞,那是因为生成器中的错误。如果你听说过碰撞发生,你可以相当肯定碰撞是因为使用了低级的随机数生成器。

来自网络各地的引语

| 如果你生成103万亿个UUID v4,碰撞的概率大约是十亿分之一。

| 如果你有1PB的UUID数据库,单次碰撞的概率是五十亿分之一。

| 如果你每秒生成80亿个UUID,

<?php
echo Charm\Id::make();
// "47e3c427-3f82-4dc7-a6ca-c83561a9cdfb"

UUID v1

此UUID保证是唯一的,前提是你有一个唯一的machine ID - 例如使用MAC地址。

<?php
echo Charm\Id::v1();
// "c85fb57a-f391-11eb-bb00-0242ee781401"
<?php
/**
 * UUID v4
 *
 * An ID that can be shared with others, and you should never see a collision.
 */
$uniqueId = Charm\Id::make();               // returns a 36 char string
// "47e3c427-3f82-4dc7-a6ca-c83561a9cdfb"

/**
 * Snowflake, by Twitter
 *
 * A 64 bit integer which can be considered unique within your organization, built from
 * a timestamp, a machine id and a sequence number.
 */
$snowflakeId = Charm\Id::snowflake(); // returns 64 bit int value
// 262805082062461697

服务对象API

<?php
use Charm\Util\IdFactory;

$idGenerator = new IdFactory(IdFactory::TYPE_UUID_V1, [
    /**
     * If you specify a machine id here, no effort is needed to retrieve a machine id.
     * The value should be globally unique for UUID V1, or unique for the organization
     * for snowflake/instaflake/sonyflake type IDs.
     */
    'machineId' => null,

    /**
     * The sequence number is a number which is supposed to ensure that we don't generate
     * two IDs on the same computer within the same time interval. The default value is derived
     * from `getmypid()` which should cause diffent workers to start on a different sequence
     * number.
     */
    'initialSequenceNumber' => null,

    /**
     * The epoch for the snowflake and derivatives ID generators is a unix
     * timestamp.
     */
    'epoch' => strtotime('2019-01-01 00:00:00'),

    /**
     * Allow fetching the computers mac address for machine id?
     */
    'allowMacAddress' => true,

    /**
     * Allow using the Kubernetes hostname UID part for machine id?
     */
    'allowKubernetesId' => true,

    /**
     * Allow unique machine ID from /var/lib/dbus/machine-id or on Windows, the registry entry in 
     * 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\MachineGuid'?
     */
    'allowMachineId' => true,

    /**
     * You can provide a custom function that provides a unique ID for the machine. The function
     * must return a positive integer or NULL.
     */
    'customMachineIdFunction' => null,
]);

// Generate a new ID. The type of ID is determined by the `$type` specified in the constructor.
$idGenerator(); // c85fb57a-f391-11eb-bb00-0242ee781401

静态API

<?php
use Charm\Id;
use Charm\Util\IdFactory;

// Optionally configure the library before generating any IDs.
Id::configure(IdFactory::TYPE_UUID_V4, [ /* options, see above */);

// Generate the default ID type
Id::make();
// 47e3c427-3f82-4dc7-a6ca-c83561a9cdfb

// Or use any of the other factory methods to create a particular type of ID

Charm\Id::uuid1();
// c85fb57a-f391-11eb-bb00-0242ee781401

Charm\Id::uuid4();
// 47e3c427-3f82-4dc7-a6ca-c83561a9cdfb

Charm\Id::comb();
// 061089ba-be18-475b-90ed-0242ee781401

Charm\Id::snowflake();
// 262805082062461697

Charm\Id::instaflake();
// 262805082067699458

Charm\Id::sonyflake();
// 33064438777189377

配置

配置是通过IdFactory构造函数或Id::configure()方法完成的。有关最新的配置选项,请参阅IdFactory源文件。

比较

  • UUID v1提供128位RFC4122兼容的UUID版本1变体1。它被设计成在全球任何数据中心和计算机上总是具有全球唯一性。它使用48位来唯一标识其运行的计算机,以及自1582年10月15日起的60位时间戳,以100纳秒为增量。碰撞的概率极小。

  • UUID v4提供128位RFC4122兼容的UUID v4变体1(也称为GUID)。它由一个非常大的122位随机数组成。生成器使用random_bytes(),它消耗被认为是加密安全的随机数。

  • COMB UUID伪装成128位RFC4122兼容的UUID v4,但它使用与UUID v1相同的原理:60位时间戳、14位序列ID和48位机器ID,按顺序排列。

  • Snowflake是一个64位整数,适合存储在数据库中,并且可以保证数据中心和服务器之间唯一ID的唯一性 - 假设machine ID是唯一的。

  • Instaflake和Sonyflake是Snowflake的不同变体,在时间戳分辨率和机器数量方面有不同的优先级。

雪花算法及其变体通常足以满足Twitter或Instagram规模的内部分配ID方案。许多人认为UUID过于庞大,不适合在数据库内部广泛使用——但它们在生成API的唯一ID或允许外部客户端离线生成ID方面非常有用。