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 |
| 4 | 122 случайных бита | нет часов или порядок не важен |
| 6 | переупорядоченный v1, сортируется по времени | совместимость с v1 |
| 7 | 48 бит времени 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 затем выставляют поверх случайных данных.
Источники
- 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 без необходимости
- 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 кГц
Нашли ошибку? ·
Смотрите также
- Base64Запись двоичных данных 64 печатными символами: алфавит, группы по 3 байта, дополнение «=», base64url
- Аппаратный генератор случайных чиселБлок микроконтроллера, который выдаёт случайные числа на основе физического шума
- Криптографическая хеш-функция (SHA)Функция, сжимающая сообщение в дайджест, к которому нельзя подобрать другое сообщение
- GATT (профиль атрибутов BLE)Структура данных Bluetooth LE: сервисы, характеристики, уведомления
- SNTPПодмножество NTPv4 для клиентов с одним сервером: пакет 48 байт, порт 123, 64-битная метка времени с 1900 года
- MQTTПротокол издатель — подписчик через брокер: топики, QoS, retain, Last Will
- Bluetooth LE для разработчикаPHY 1M/2M/Coded, каналы 37–39, реклама, GAP и GATT, MTU, интервал соединения, скорость
- ESP32ESP32, S2, S3, C2, C3, C5, C6, H2, P4: ядра, радио, USB, GPIO — сравнение и выбор