version1.rst 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. .. _rfc4122.version1:
  2. =========================
  3. Version 1: Gregorian Time
  4. =========================
  5. .. attention::
  6. If you need a time-based UUID, and you don't need the other features
  7. included in version 1 UUIDs, we recommend using
  8. :ref:`version 7 UUIDs <rfc4122.version7>`.
  9. A version 1 UUID uses the current time, along with the MAC address (or *node*)
  10. for a network interface on the local machine. This serves two purposes:
  11. 1. You can know *when* the identifier was created.
  12. 2. You can know *where* the identifier was created.
  13. In a distributed system, these two pieces of information can be valuable. Not
  14. only is there no need for a central authority to generate identifiers, but you
  15. can determine what nodes in your infrastructure created the UUIDs and at what
  16. time.
  17. .. tip::
  18. It is also possible to use a **randomly-generated node**, rather than a
  19. hardware address. This is useful for when you don't want to leak machine
  20. information, while still using a UUID based on time. Keep reading to find
  21. out how.
  22. By default, ramsey/uuid will attempt to look up a MAC address for the machine it
  23. is running on, using this value as the node. If it cannot find a MAC address, it
  24. will generate a random node.
  25. .. code-block:: php
  26. :caption: Generate a version 1, Gregorian time UUID
  27. :name: rfc4122.version1.example
  28. use Ramsey\Uuid\Uuid;
  29. $uuid = Uuid::uuid1();
  30. printf(
  31. "UUID: %s\nVersion: %d\nDate: %s\nNode: %s\n",
  32. $uuid->toString(),
  33. $uuid->getFields()->getVersion(),
  34. $uuid->getDateTime()->format('r'),
  35. $uuid->getFields()->getNode()->toString()
  36. );
  37. This will generate a version 1 UUID and print out its string representation, the
  38. time the UUID was created, and the node used to create the UUID.
  39. It will look something like this:
  40. .. code-block:: text
  41. UUID: e22e1622-5c14-11ea-b2f3-0242ac130003
  42. Version: 1
  43. Date: Sun, 01 Mar 2020 23:32:15 +0000
  44. Node: 0242ac130003
  45. You may provide custom values for version 1 UUIDs, including node and clock
  46. sequence.
  47. .. code-block:: php
  48. :caption: Provide custom node and clock sequence to create a version 1,
  49. Gregorian time UUID
  50. :name: rfc4122.version1.custom-example
  51. use Ramsey\Uuid\Provider\Node\StaticNodeProvider;
  52. use Ramsey\Uuid\Type\Hexadecimal;
  53. use Ramsey\Uuid\Uuid;
  54. $nodeProvider = new StaticNodeProvider(new Hexadecimal('121212121212'));
  55. $clockSequence = 16383;
  56. $uuid = Uuid::uuid1($nodeProvider->getNode(), $clockSequence);
  57. .. tip::
  58. Version 1 UUIDs generated in ramsey/uuid are instances of UuidV1. Check out
  59. the :php:class:`Ramsey\\Uuid\\Rfc4122\\UuidV1` API documentation to learn
  60. more about what you can do with a UuidV1 instance.
  61. .. _rfc4122.version1.custom:
  62. Providing a Custom Node
  63. #######################
  64. You may override the default behavior by passing your own node value when
  65. generating a version 1 UUID.
  66. In the :ref:`example above <rfc4122.version1.custom-example>`, we saw how to
  67. pass a custom node and clock sequence. An interesting thing to note about the
  68. example is its use of StaticNodeProvider. Why didn't we pass in a
  69. :php:class:`Hexadecimal <Ramsey\\Uuid\\Type\\Hexadecimal>` value, instead?
  70. According to `RFC 4122, section 4.5`_, node values that do not identify the
  71. host --- in other words, our own custom node value --- should set the
  72. unicast/multicast bit to one (1). This bit will never be set in IEEE 802
  73. addresses obtained from network cards, so it helps to distinguish it from a
  74. hardware MAC address.
  75. The StaticNodeProvider sets this bit for you. This is why we used it rather
  76. than providing a :php:class:`Hexadecimal <Ramsey\\Uuid\\Type\\Hexadecimal>`
  77. value directly.
  78. Recall from the example that the node value we set was ``121212121212``, but if
  79. you take a look at this value with ``$uuid->getFields()->getNode()->toString()``,
  80. it becomes:
  81. .. code-block:: text
  82. 131212121212
  83. That's a result of this bit being set by the StaticNodeProvider.
  84. .. _rfc4122.version1.random:
  85. Generating a Random Node
  86. ########################
  87. Instead of providing a custom node, you may also generate a random node each
  88. time you generate a version 1 UUID. The RandomNodeProvider may be used to
  89. generate a random node value, and like the StaticNodeProvider, it also sets the
  90. unicast/multicast bit for you.
  91. .. code-block:: php
  92. :caption: Provide a random node value to create a version 1, Gregorian time UUID
  93. :name: rfc4122.version1.random-example
  94. use Ramsey\Uuid\Provider\Node\RandomNodeProvider;
  95. use Ramsey\Uuid\Uuid;
  96. $nodeProvider = new RandomNodeProvider();
  97. $uuid = Uuid::uuid1($nodeProvider->getNode());
  98. .. _rfc4122.version1.clock:
  99. What's a Clock Sequence?
  100. ########################
  101. The clock sequence part of a version 1 UUID helps prevent collisions. Since this
  102. UUID is based on a timestamp and a machine node value, it is possible for
  103. collisions to occur for multiple UUIDs generated within the same microsecond on
  104. the same machine.
  105. The clock sequence is the solution to this problem.
  106. The clock sequence is a 14-bit number --- this supports values from 0 to 16,383
  107. --- which means it should be possible to generate up to 16,384 UUIDs per
  108. microsecond with the same node value, before hitting a collision.
  109. .. caution::
  110. ramsey/uuid does not use *stable storage* for clock sequence values.
  111. Instead, all clock sequences are randomly-generated. If you are generating
  112. a lot of version 1 UUIDs every microsecond, it is possible to hit collisions
  113. because of the random values. If this is the case, you should use your own
  114. mechanism for generating clock sequence values, to ensure against
  115. randomly-generated duplicates.
  116. See `section 4.2 of RFC 4122`_, for more information.
  117. .. _rfc4122.version1.privacy:
  118. Privacy Concerns
  119. ################
  120. As discussed earlier in this section, version 1 UUIDs use a MAC address from a
  121. local hardware network interface. This means it is possible to uniquely identify
  122. the machine on which a version 1 UUID was created.
  123. If the value provided by the timestamp of a version 1 UUID is important to you,
  124. but you do not wish to expose the interface address of any of your local
  125. machines, see :ref:`rfc4122.version1.random` or :ref:`rfc4122.version1.custom`.
  126. If you do not need an identifier with a timestamp value embedded in it, see
  127. :ref:`rfc4122.version4` to learn about random UUIDs.
  128. .. _RFC 4122: https://tools.ietf.org/html/rfc4122
  129. .. _RFC 4122, section 4.5: https://tools.ietf.org/html/rfc4122#section-4.5
  130. .. _section 4.2 of RFC 4122: https://tools.ietf.org/html/rfc4122#section-4.2