Рандомный айди
Справка по алгоритмам
Сравнительная таблица
| Критерий | UUIDv4 | UUIDv7 | Snowflake | Randflake | Фейстель |
|---|---|---|---|---|---|
| Размер | 128 бит | 128 бит | 64 бита | 64 бита | 64 бита |
| Непредсказуемость | Да | Частично | Нет | Да | Да |
| Упорядоченность | Нет | Да | Да | Нет | Нет |
| Миграция БД | Да | Да | Да | Да | Нет |
| Стабильные ссылки | Нет | Нет | Да | Да | Да |
Рекомендации по выбору
- Новый проект: UUIDv7 – современный стандарт
- Без миграций: Фейстель – внедряется за вечер
- Высокая нагрузка: Randflake – 17 млрд ID/с
- Упорядоченность: Snowflake – если предсказуемость не критична
Когда API отдаёт URL вида /invoices/1043, /invoices/1044, /invoices/1045 – достаточно одного валидного адреса и цикла for, чтобы выкачать всю таблицу. Именно так в апреле 2025 года утекли парковочные счета APCOA по пяти странам. Эта уязвимость – Broken Access Control / IDOR – год за годом возглавляет рейтинг OWASP. Рандомный айди – минимальная защита, которая делает перебор невозможным.
Что такое рандомный айди и каким он должен быть
Рандомный айди – идентификатор записи, который нельзя угадать, зная соседние значения. Хороший рандомный ID обладает четырьмя свойствами:
- Уникальность – два генератора никогда не создадут одинаковый ID
- Непредсказуемость – по одному значению невозможно вычислить другое
- Равномерность – значения распределены по диапазону равномерно, что важно для шардирования
- Обратимость (опционально) – возможность восстановить исходный ID без хранения таблицы соответствий
Простой вызов random() с проверкой в БД формально решает задачу, но требует обращения к базе на каждую генерацию. В распределённой системе это создаёт задержку и единую точку отказа.
Какие существуют подходы к генерации рандомного айди
UUID
Universally Unique Identifier – 128-битный стандарт, наиболее распространённая версия – UUIDv4 (полностью случайный). В 2026 году набирает популярность UUIDv7, сочетающий временную метку и случайную часть.
Плюсы: стандартизирован, встроен в большинство языков и баз данных, не требует координации между узлами.
Минусы: 128 бит вместо 64 – раздутые индексы и джойны; UUIDv4 фрагментирует B-tree; нет стабильности ссылок при пересоздании записей.
Snowflake ID
Алгоритм, разработанный X (ранее Twitter), генерирует 64-битные k-сортированные ID из трёх компонентов: временная метка, ID узла, локальный счётчик.
Плюсы: компактный 64-битный формат, упорядоченность по времени, высокая пропускная способность.
Минусы: ID предсказуемы – зная структуру, можно вычислить соседние значения; требуется координация ID узлов.
Randflake ID
Randflake – расширение Snowflake с добавлением блочного шифра sparx64. Структура 64-битного ID: 30 бит – метка времени Unix, 17 бит – ID узла, 17 бит – локальный счётчик, затем весь блок шифруется.
Блочный шифр – криптографическая функция, которая преобразует блок открытого текста в блок шифротекста той же длины по ключу. Ключевое свойство: это биекция, то есть каждый уникальный вход даёт уникальный выход, и наоборот. Это гарантирует уникальность после шифрования.
Характеристики Randflake:
| Параметр | Значение |
|---|---|
| Размер ID | 64 бита |
| Точность метки времени | секунда |
| Максимум узлов | 131 072 |
| Максимум ID в секунду на узел | 131 072 |
| Теоретическая пропускная способность | 17 179 869 184 ID/с |
| Срок службы | ~34 года от эпохи |
Randflake раскрывает метку времени и ID узла только владельцу секретного ключа, обеспечивая внутреннюю отслеживаемость.
Шифрование Фейстелем
Подход для существующих проектов: вместо замены автоинкрементных PK в базе, их шифруют на границе API. Сеть Фейстеля – конструкция из нескольких раундов, где вход делится пополам, одна часть XOR-ится с раундовой функцией от другой части и ключа, половины меняются местами. Обратимость даёт сама структура, даже если раундовая функция необратима.
for i in range(rounds):
f = round_function(right, key, i)
new_right = left ^ f
left = right
right = new_right
8 раундов SHA-256 как раундовой функции – доли микросекунды на CPU. Последовательные ID 1, 2, 3 превращаются в 5823901847263..., 9174625038192..., 2847193650471....
Плюсы: ноль миграций, ноль изменений в БД, биекция вместо хеша (нет коллизий), стабильные URL.
Минусы: не заменяет авторизацию; утёкший ключ = полный перебор; ротация ключа ломает все публичные ссылки.
Какой рандомный айди выбрать – сравнение подходов
| Критерий | UUIDv4 | UUIDv7 | Snowflake | Randflake | Фейстель |
|---|---|---|---|---|---|
| Размер | 128 бит | 128 бит | 64 бита | 64 бита | 64 бита |
| Уникальность без БД | Да | Да | Да | Да | Да |
| Непредсказуемость | Да | Частично | Нет | Да | Да |
| Упорядоченность | Нет | Да | Да | Нет | Нет |
| Равномерное распределение | Да | Нет | Нет | Да | Да |
| Требует координации узлов | Нет | Нет | Да | Да | Нет |
| Миграция БД | Да | Да | Да | Да | Нет |
| Стабильные ссылки | Нет | Нет | Да | Да | Да |
Как реализовать Randflake ID
Калькулятор выше позволяет сгенерировать рандомный айди в разных форматах. Для продакшен-реализации Randflake используется следующий подход:
import time, struct
from sparx64 import Sparx64
EPOCH_OFFSET = 1730000000 # 27 октября 2024 UTC
TIMESTAMP_BITS = 30
NODE_BITS = 17
SEQ_BITS = 17
class Randflake:
def __init__(self, node_id: int, secret: bytes):
self.node_id = node_id
self.sequence = 0
self.rollover = int(time.time())
self.sbox = Sparx64(secret)
def _new_raw(self) -> int:
while True:
now = int(time.time())
self.sequence += 1
seq = self.sequence
if seq > (1 << SEQ_BITS) - 1:
if now > self.rollover:
self.sequence = 0
self.rollover = now
seq = 0
else:
continue
ts = now - EPOCH_OFFSET
return (ts << 34) | (self.node_id << 17) | seq
def generate(self) -> int:
raw = self._new_raw()
src = struct.pack("<q", raw)
dst = bytearray(8)
self.sbox.encrypt(dst, src)
return struct.unpack("<q", dst)[0]
Координация ID узлов реализуется через механизм аренды: центральная служба назначает уникальный node_id каждому генератору на ограниченный период. Это сокращает обращения к службе координации до одного за период продления.
Когда какой подход применять
Новый проект без ограничений – UUIDv7. Упорядоченный, стандартизированный, не требует координации.
Существующая БД с автоинкрементом, миграция невозможна – шифрование Фейстелем. Внедряется за вечер, не трогает схему.
Высоконагруженная распределённая система – Randflake. 17 млрд ID в секунду, равномерное распределение для шардирования, внутренняя отслеживаемость.
Нужна упорядоченность + компактность, предсказуемость не критична – Snowflake. Проще Randflake, но без защиты от перебора.
Защита от сбоев часов в распределённых генераторах
Проблема сдвига часов (clock drift) – одна из основных для time-based генераторов. Randflake решает её двумя механизмами:
- Проверка при аренде – служба координации гарантирует, что время начала новой аренды ≥ времени начала предыдущей
- Отклонение запросов – генератор отклоняет вызовы, если текущая метка времени меньше начала аренды или больше окончания
Это предотвращает генерацию дубликатов при обратном скачке часов.
Информация о криптографических алгоритмах носит ознакомительный характер. Для защиты конфиденциальных данных используйте сертифицированные средства шифрования.