charm / uuid
一个非常快速且无依赖的库,用于生成UUID(GUID)版本1或4,可排序的UUID且验证通过,或者根据Twitter的Snowflake、Sonyflake或Instaflake算法生成的64位唯一标识符。
Requires (Dev)
- ramsey/uuid: ^4.1
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
文件以获取详细信息。值得注意的是
- 生成第一个UUID少于1毫秒,比
ramsey/uuid
的UUID v1快10.5毫秒,比UUID v4快3.9毫秒。 - 开销与加载源文件有关。
这些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方面非常有用。