mirror of
https://github.com/ramsey/uuid.git
synced 2026-06-14 15:56:48 +03:00
185 lines
6.3 KiB
ReStructuredText
185 lines
6.3 KiB
ReStructuredText
.. _rfc4122.version1:
|
|
|
|
=====================
|
|
Version 1: Time-based
|
|
=====================
|
|
|
|
A version 1 UUID uses the current time, along with the MAC address (or *node*)
|
|
for a network interface on the local machine. This serves two purposes:
|
|
|
|
1. You can know *when* the identifier was created.
|
|
2. You can know *where* the identifier was created.
|
|
|
|
In a distributed system, these two pieces of information can be valuable. Not
|
|
only is there no need for a central authority to generate identifiers, but you
|
|
can determine what nodes in your infrastructure created the UUIDs and at what
|
|
time.
|
|
|
|
.. tip::
|
|
|
|
It is also possible to use a **randomly-generated node**, rather than a
|
|
hardware address. This is useful for when you don't want to leak machine
|
|
information, while still using a UUID based on time. Keep reading to find
|
|
out how.
|
|
|
|
By default, ramsey/uuid will attempt to look up a MAC address for the machine it
|
|
is running on, using this value as the node. If it cannot find a MAC address, it
|
|
will generate a random node.
|
|
|
|
.. code-block:: php
|
|
:caption: Generate a version 1, time-based UUID
|
|
:name: rfc4122.version1.example
|
|
|
|
use Ramsey\Uuid\Uuid;
|
|
|
|
$uuid = Uuid::uuid1();
|
|
|
|
printf(
|
|
"UUID: %s\nVersion: %d\nDate: %s\nNode: %s\n",
|
|
$uuid->toString(),
|
|
$uuid->getFields()->getVersion(),
|
|
$uuid->getDateTime()->format('r'),
|
|
$uuid->getFields()->getNode()->toString()
|
|
);
|
|
|
|
This will generate a version 1 UUID and print out its string representation, the
|
|
time the UUID was created, and the node used to create the UUID.
|
|
|
|
It will look something like this:
|
|
|
|
.. code-block:: text
|
|
|
|
UUID: e22e1622-5c14-11ea-b2f3-0242ac130003
|
|
Version: 1
|
|
Date: Sun, 01 Mar 2020 23:32:15 +0000
|
|
Node: 0242ac130003
|
|
|
|
You may provide custom values for version 1 UUIDs, including node and clock
|
|
sequence.
|
|
|
|
.. code-block:: php
|
|
:caption: Provide custom node and clock sequence to create a version 1,
|
|
time-based UUID
|
|
:name: rfc4122.version1.custom-example
|
|
|
|
use Ramsey\Uuid\Provider\Node\StaticNodeProvider;
|
|
use Ramsey\Uuid\Type\Hexadecimal;
|
|
use Ramsey\Uuid\Uuid;
|
|
|
|
$nodeProvider = new StaticNodeProvider(new Hexadecimal('121212121212'));
|
|
$clockSequence = 16383;
|
|
|
|
$uuid = Uuid::uuid1($nodeProvider->getNode(), $clockSequence);
|
|
|
|
.. tip::
|
|
|
|
Version 1 UUIDs generated in ramsey/uuid are instances of UuidV1. Check out
|
|
the :php:class:`Ramsey\\Uuid\\Rfc4122\\UuidV1` API documentation to learn
|
|
more about what you can do with a UuidV1 instance.
|
|
|
|
|
|
.. _rfc4122.version1.custom:
|
|
|
|
Providing a Custom Node
|
|
#######################
|
|
|
|
You may override the default behavior by passing your own node value when
|
|
generating a version 1 UUID.
|
|
|
|
In the :ref:`example above <rfc4122.version1.custom-example>`, we saw how to
|
|
pass a custom node and clock sequence. An interesting thing to note about the
|
|
example is its use of StaticNodeProvider. Why didn't we pass in a
|
|
:php:class:`Hexadecimal <Ramsey\\Uuid\\Type\\Hexadecimal>` value, instead?
|
|
|
|
According to `RFC 4122, section 4.5`_, node values that do not identify the
|
|
host --- in other words, our own custom node value --- should set the
|
|
unicast/multicast bit to one (1). This bit will never be set in IEEE 802
|
|
addresses obtained from network cards, so it helps to distinguish it from a
|
|
hardware MAC address.
|
|
|
|
The StaticNodeProvider sets this bit for you. This is why we used it rather
|
|
than providing a :php:class:`Hexadecimal <Ramsey\\Uuid\\Type\\Hexadecimal>`
|
|
value directly.
|
|
|
|
Recall from the example that the node value we set was ``121212121212``, but if
|
|
you take a look at this value with ``$uuid->getFields()->getNode()->toString()``,
|
|
it becomes:
|
|
|
|
.. code-block:: text
|
|
|
|
131212121212
|
|
|
|
That's a result of this bit being set by the StaticNodeProvider.
|
|
|
|
|
|
.. _rfc4122.version1.random:
|
|
|
|
Generating a Random Node
|
|
########################
|
|
|
|
Instead of providing a custom node, you may also generate a random node each
|
|
time you generate a version 1 UUID. The RandomNodeProvider may be used to
|
|
generate a random node value, and like the StaticNodeProvider, it also sets the
|
|
unicast/multicast bit for you.
|
|
|
|
.. code-block:: php
|
|
:caption: Provide a random node value to create a version 1, time-based UUID
|
|
:name: rfc4122.version1.random-example
|
|
|
|
use Ramsey\Uuid\Provider\Node\RandomNodeProvider;
|
|
use Ramsey\Uuid\Uuid;
|
|
|
|
$nodeProvider = new RandomNodeProvider();
|
|
|
|
$uuid = Uuid::uuid1($nodeProvider->getNode());
|
|
|
|
|
|
.. _rfc4122.version1.clock:
|
|
|
|
What's a Clock Sequence?
|
|
########################
|
|
|
|
The clock sequence part of a version 1 UUID helps prevent collisions. Since this
|
|
UUID is based on a timestamp and a machine node value, it is possible for
|
|
collisions to occur for multiple UUIDs generated within the same microsecond on
|
|
the same machine.
|
|
|
|
The clock sequence is the solution to this problem.
|
|
|
|
The clock sequence is a 14-bit number --- this supports values from 0 to 16,383
|
|
--- which means it should be possible to generate up to 16,384 UUIDs per
|
|
microsecond with the same node value, before hitting a collision.
|
|
|
|
.. caution::
|
|
|
|
ramsey/uuid does not use *stable storage* for clock sequence values.
|
|
Instead, all clock sequences are randomly-generated. If you are generating
|
|
a lot of version 1 UUIDs every microsecond, it is possible to hit collisions
|
|
because of the random values. If this is the case, you should use your own
|
|
mechanism for generating clock sequence values, to ensure against
|
|
randomly-generated duplicates.
|
|
|
|
See `section 4.2 of RFC 4122`_, for more information.
|
|
|
|
|
|
.. _rfc4122.version1.privacy:
|
|
|
|
Privacy Concerns
|
|
################
|
|
|
|
As discussed earlier in this section, version 1 UUIDs use a MAC address from a
|
|
local hardware network interface. This means it is possible to uniquely identify
|
|
the machine on which a version 1 UUID was created.
|
|
|
|
If the value provided by the timestamp of a version 1 UUID is important to you,
|
|
but you do not wish to expose the interface address of any of your local
|
|
machines, see :ref:`rfc4122.version1.random` or :ref:`rfc4122.version1.custom`.
|
|
|
|
If you do not need an identifier with a timestamp value embedded in it, see
|
|
:ref:`rfc4122.version4` to learn about random UUIDs.
|
|
|
|
|
|
.. _RFC 4122: https://tools.ietf.org/html/rfc4122
|
|
.. _RFC 4122, section 4.5: https://tools.ietf.org/html/rfc4122#section-4.5
|
|
.. _section 4.2 of RFC 4122: https://tools.ietf.org/html/rfc4122#section-4.2
|