Перейти к содержанию

UUID

Чтобы устройства, серверы и записи в базе не путались, каждому выдают идентификатор, уникальный без согласования с кем-либо. UUID решает это 128 битами: либо почти целиком случайными, либо с меткой времени в старших разрядах, чтобы идентификаторы сортировались.

Обновлено Редакция GAW

UUID (Universally Unique IDentifier, универсальный уникальный идентификатор; в мире Microsoft — GUID) — 128-битное число, которое по RFC 9562 можно создать на любой машине без центральной регистрации и считать уникальным в масштабе мира. Алгоритм допускает генерацию 10 млн значений в секунду на машину и более, а 16 байт удобно хранить, сравнивать и сортировать — отсюда UUID в базах данных, журналах и в идентификаторах сервисов BLE.

Формат

UUID состоит из 16 октетов в сетевом порядке байт (старший первым); RFC отдельно оговаривает, что GUID в Microsoft COM сохраняются в little-endian. Текстовая форма «hex-and-dash» — пять групп шестнадцатеричных цифр через дефис, 8-4-4-4-12, в любом регистре: f81d4fae-7dec-11d0-a765-00a0c91e6bf6; с префиксом urn:uuid: это URN. Два поля зарезервированы под служебные биты: variant в старших битах октета 8 — у стандартных UUID биты 64 и 65 равны 10, поэтому первая цифра четвёртой группы всегда 8, 9, A или B, — и version в старших 4 битах октета 6. По шаблону xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx цифра M и есть версия.

ВерсияСодержимое (RFC 9562, табл. 2)Когда применять
1метка григорианского времени и идентификатор узлаустаревший, RFC советует v7
3, 5хеш имени в пространстве имён (MD5, SHA-1)один и тот же вход даёт тот же UUID
4122 случайных битанет часов или порядок не важен
6переупорядоченный v1, сортируется по временисовместимость с v1
748 бит времени Unix в мс плюс 74 бита случайных данных или счётчикаключи БД, журналы, события
8пользовательский форматсвои схемы

Отдельно определены Nil UUID из одних нулей («значения нет») и Max UUID из одних единиц («конец списка»).

Версии 4 и 7

UUIDv4 (разд. 5.4) — это 128 случайных бит, в которых шесть заменены на версию и variant; остаётся 122 бита, то есть около 5,3·10^36 значений (наш расчёт). Коллизии при добротном генераторе практически исключены, но RFC (разд. 6.7) просит оценивать их цену: дубликат записи в журнале — пустяк, дубликат ключа в системе управления — нет. Источник случайности должен быть криптографически стойким (разд. 6.9): на ESP32 истинно случайные байты даёт esp_fill_random() от аппаратного ГСЧ, пока включено радио или источник энтропии активирован bootloader_random_enable().

UUIDv7 (разд. 5.7) кладёт в старшие 48 бит время Unix в миллисекундах, а оставшиеся 74 бита заполняет случайными данными либо, для монотонности внутри миллисекунды, долей миллисекунды (до 12 бит) и счётчиком. Такие идентификаторы сортируются по времени создания как непрозрачные байты и попадают в индекс базы рядом друг с другом; RFC оценивает выигрыш в локальности индекса на порядок (разд. 6.11) и рекомендует v7 вместо v1 и v6. Контроллеру для v7 нужны верные часы — после синхронизации по SNTP — и защита от хода часов назад.

UUID в BLE и в протоколах

В Bluetooth Low Energy сервисы и характеристики GATT адресуются UUID; в ESP-IDF их описывает структура esp_bt_uuid_t с полем len — 16, 32 или 128 бит — и массивом uuid128 для полной формы. Короткая форма встречается у стандартных характеристик — например, Peripheral Preferred Connection Parameters имеет UUID 0x2A04 в Kconfig ESP-IDF, — а 128-битная по размеру совпадает с UUID из RFC 9562, и для неё годится тот же генератор. В MQTT и REST UUID устройства обычно служит идентификатором клиента или частью топика; передают его шестнадцатеричной строкой из 36 символов, а не 16 байтами или Base64, — читаемость в журналах важнее. Версии 3 и 5 строят UUID из имени через хеш-функцию: так одно и то же имя устройства всегда даёт один и тот же идентификатор.

Частые вопросы

Чем UUID версии 7 лучше версии 4?

UUIDv4 — 122 случайных бита, у него нет никакой структуры, и в индексе базы данных новые ключи ложатся вразброс. UUIDv7 ставит в старшие 48 бит метку времени Unix в миллисекундах, а остальные 74 бита заполняет случайными данными или счётчиком, поэтому идентификаторы сортируются по времени создания как обычные байты и ложатся в индекс рядом — RFC 9562 (разд. 6.11) говорит о разнице в производительности на порядок. Для v7 нужны верные часы; если их нет, остаётся v4.

Как по строке понять версию UUID?

По шаблону xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx из RFC 9562: цифра M — версия (старшие 4 бита октета 6), цифра N — variant, у стандартных UUID это 8, 9, A или B, потому что биты 64 и 65 равны 1 и 0. Например, в 00000000-0000-4000-8000-000000000000 версия 4. Сам RFC при этом советует не разбирать UUID без нужды и обращаться с ним как с непрозрачным значением (разд. 6.12).

Можно ли генерировать UUID на микроконтроллере?

Да, для v4 нужны 122 случайных бита, а RFC 9562 (разд. 6.9) требует криптографически стойкого источника: предсказуемый генератор даёт повторы и угадываемые идентификаторы. На ESP32 функция esp_fill_random() даёт истинно случайные байты от аппаратного генератора, пока включено радио Wi-Fi или Bluetooth либо источник энтропии включён bootloader_random_enable(); без этого числа только псевдослучайные. Версии и variant затем выставляют поверх случайных данных.

Источники

  1. IETF. RFC 9562 Universally Unique IDentifiers (UUIDs). K. Davis, B. Peabody, P. Leach, May 2024 — разд. 1: UUID, он же GUID, 128 бит, центральной регистрации не требует; разд. 2: алгоритм поддерживает генерацию 10 млн в секунду на машину и более; разд. 4: 16 октетов, поля в сетевом порядке байт (старший байт первым), оговорка о little-endian в GUID COM; строковая форма «hex-and-dash»: 8-4-4-4-12 шестнадцатеричных цифр в любом регистре, пример f81d4fae-7dec-11d0-a765-00a0c91e6bf6, форма URN urn:uuid:…; разд. 4.1: поле variant в старших битах октета 8, для UUID этого документа биты 64 и 65 равны 1 и 0 (шестнадцатеричные 8, 9, A, B); разд. 4.2: версия — старшие 4 бита октета 6, таблица 2: 1 — по григорианскому времени, 3 — по имени с MD5, 4 — случайный, 5 — по имени с SHA-1, 6 — переупорядоченный по времени, 7 — по времени Unix, 8 — пользовательский; шаблон xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx; разд. 5.4: UUIDv4 — 122 случайных бита (random_a 48, random_b 12, random_c 62) плюс версия и variant; разд. 5.7: UUIDv7 — 48-битная метка времени Unix в миллисекундах в старших битах, остальные 74 бита случайные либо доля миллисекунды (до 12 бит) и счётчик для монотонности; следует предпочитать v7 вместо v1 и v6; разд. 5.9–5.10: Nil UUID из нулей и Max UUID из единиц; разд. 6.7: оценивать последствия коллизий; разд. 6.9: генерировать криптографически стойким ГПСЧ; разд. 6.11: v6 и v7 сортируются как непрозрачные байты, улучшают локальность индексов БД; разд. 6.12: не разбирать UUID без необходимости
  2. Espressif. ESP-IDF Programming Guide v6.1, ESP32: Bluetooth Define (esp_bt_defs.h); Random Number Generation — структура esp_bt_uuid_t: поле len — длина UUID 16, 32 или 128 бит, объединение uuid16, uuid32 и массив uuid128[ESP_UUID_LEN_128]; страница Random Number Generation (api-reference/system/random.html): esp_random() и esp_fill_random() читают аппаратный ГСЧ, истинно случайные числа — при включённом радио Wi-Fi или Bluetooth либо после bootloader_random_enable(), иначе только псевдослучайные; чтение не чаще 15–75 кГц
Страница помогла?

Нашли ошибку? ·