Обновлено:
Рандомный айди
Справка по алгоритмам
Сравнительная таблица
| Критерий | 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 решает её двумя механизмами:
- Проверка при аренде – служба координации гарантирует, что время начала новой аренды ≥ времени начала предыдущей
- Отклонение запросов – генератор отклоняет вызовы, если текущая метка времени меньше начала аренды или больше окончания
Это предотвращает генерацию дубликатов при обратном скачке часов.
Информация о криптографических алгоритмах носит ознакомительный характер. Для защиты конфиденциальных данных используйте сертифицированные средства шифрования.
Часто задаваемые вопросы
Зачем нужен рандомный айди вместо автоинкремента?
Последовательные ID позволяют перебрать все записи простым циклом – это уязвимость IDOR из топа OWASP. Рандомный айди делает соседние значения непредсказуемыми и закрывает массовый перебор.
Чем UUID отличается от зашифрованного последовательного ID?
UUID генерируется случайно при вставке, даёт фрагментированные индексы и нестабильные ссылки. Зашифрованный ID – чистая функция от PK: индекс остаётся плотным, а публичный идентификатор – стабильным при восстановлении из бэкапа.
Можно ли использовать рандомный айди как ключ шардирования?
Да, если распределение равномерное. Randflake и UUID дают равномерное распределение, подходящее для шардинга. Зашифрованные Фейстелем ID тоже равномерны при корректном ключе.
Что делать при компрометации ключа шифрования ID?
Утёкший ключ означает, что атакующий сможет перебирать записи. Немедленно ротируйте ключ, но учтите: все публичные ссылки сломаются. Храните ключ в менеджере секретов, никогда не коммитьте в репозиторий.
Какой подход выбрать для нового проекта в 2026 году?
Для новой схемы без ограничений – UUIDv7: упорядоченный, совместимый со стандартом. Для защиты существующей БД без миграций – шифрование Фейстелем. Для высоконагруженных распределённых систем – Randflake или Snowflake.