Идентификаторларды генерациялау
1) Сәйкестендіргіштерге неге назар аудару керек
Идентификатор (ID) - мәнінің іргелі кілті: ДБ жолдары, хабарламалар, файл, тапсырыс. Оның қасиеттеріне байланысты:- Бірегейлік және масштаб (коллизиялар, көлденең өсу).
- Тәртіп және сұрыптау (уақытша корреляция, репликация, дедуп).
- Сақтау өнімділігі (индекстер, ыстық беттер, кілттің өлшемі).
- Қауіпсіздік (болжамсыздық, жылыстау, болжау).
- Юзабилити/интеграция (қысқа, URL-safe, тіркелімге сезімтал емес).
ID таңдау - энтропия, ретке келтіру, ұзындық, өндіру жылдамдығы және пайдалану арасындағы ымыраға келу.
2) Негізгі талаптар мен терминдер
Бірегейлік: коллизия ықтималдығы қолайлы тәуекелден төмен болуы тиіс.
Энтропия: «қанша кездейсоқтық» құрамында ID (бит) бар.
Ретке келтіру (time-sortable/k-sortable): лексикографиялық сұрыптау ≈ уақыт бойынша сұрыптау.
Монотония: түйін/ағын ішіндегі кемімейтін бірізділік.
Жазбаның орналасуы: жаңа ендірме индекстің «артқы жағында» қаншалықты шоғырланған (ыстық беттердің қауіптілігі).
Болжамдылық: көршілес ID анықтауға бола ма (қауіпсіздік/API үшін маңызды).
Ұсыным: бинарлық/жол, Base16/32/36/58/64, дефистер, регистр.
3) Идентификаторлардың негізгі жиындары
3. 1 UUID
v4 (random): 122 энтропия биті. Реттемейміз, қауіпсіздік пен қарапайымдылық үшін жақсы. Минус: кездейсоқ бөлінуден индекстер «хаотитті» - бұл, алайда, жүктемелерді біркелкі таратып, «ыстық беттерді» алып тастайды.
v1 (time + MAC): реттейміз, бірақ МАС/уақытты алып жүреді (жекелік); жиі аулақ болады.
v7 (time-ordered): миллисекундтық уақыт + рандом бөлігі. Уақыт бойынша лексикографиялық сұрыптауға және жақсы сығымдауға арналған дизайн. Ымыраға келу: индекстің «ыстық құйрығы» пайда болады; шардалаумен/префикстермен/инкрементпен емделеді.
Кеңестер
Сыртқы API және тәртіпке қойылатын қатаң емес талаптар үшін - v4.
Оқиғалық/логикалық ДБ және «сұрыпталатын» кілттер үшін - v7.
3. 2 ULID (Crockford Base32)
128 бит: 48 бит уақыт (мс) + 80 бит кездейсоқ. Лексикографиялық жағынан уақыт бойынша сұрыпталады, адам-достық ('I, L, O, U'), URL-safe. Монотонды вариация бар (бірдей уақыт белгісінде кездейсоқ бөлігі ұлғаяды).
Артықшылықтары: оқылушылық, ретке келтіру, төзімділік.
Минустар: өте жоғары жиіліктегі ендірмелерде бір сәтте - «ыстық құйрық».
3. 3 KSUID
160 бит: 32 бит уақыт (сек) дәуірге қатысты + 128 бит кездейсоқ. Үлкен уақыт диапазоны және тұрақты сұрыптау, жолдар ULID-ден қысқа? (жоқ - ұзын, бірақ өзінің кодтауымен), бөлінген логтар мен нысандар үшін жақсы.
3. 4 Snowflake-ұқсас (k-sortable flake IDs)
Классикалық схема (теңшелетін):
[ timestamp bits ][ region/datacenter bits ][ worker bits ][ sequence bits ]
Қасиеттері: тораптағы монотонды өсу, квази-жаһандық бірегейлік, қысқа (64 бит) бинарлық көрініс.
Тәуекелдер: сағатқа тәуелділік (уақыт дрейфі/регресс), бір тиктегі sequence сарқылуы, region/worker биттерін үйлестіру.
Емделеді: «clock back» қорғанысымен, sequence резервімен, уақыт детекторымен, PTP/NTP тәртібімен.
3. 5 ДБ жүйелілігі (SEQUENCE/IDENTITY)
Бір СУБД/шардадағы қарапайым монотонды генерация.
Артықшылықтары: қысқа, жылдам, жергілікті кестелер үшін ыңғайлы.
Кемшіліктері: жаһандық деңгейде бөлінген кластерде қиын; болжауға болады (көпшілік кілті ретінде қауіпсіз емес), индекстің ыстық құйрығын жасайды.
3. 6 Контент-мекенжайлық ID (hash content)
Мазмұннан SHA-256/Blake3 → тұрақты ID, дедупликация, тұтастығын тексеру, кэштеу.
Артықшылықтары: детерминизм, ауыстырудан қорғау.
Кемшіліктері: қымбат генерация (CPU), практикалық нөлдік коллизиялар, уақытша сұрыптау жоқ, ұзындығы.
4) Коллизиялар және «туған күндер парадоксы» (интуитивті)
'n' генерацияларындағы 'b' бит 'өлшемінің кездейсоқ ID үшін коллизия ықтималдығы шамамен:
p ≈ 1 - exp (-n (n-1 )/2/2 ^ b) ≈ n ^ 2/2 ^ (b + 1) (for small p)
Мысалдар:
- UUIDv4 (122 бит) кезінде n = 10 ^ 12 (триллион) → p ~ 1e-14 (елеусіз).
- 64-бит рандом → кезінде n = 10 ^ 9 p ~ 0. 027 (елеулі тәуекел).
- Қорытынды: 64-бит кездейсоқ жиі үлкен жүйелер үшін аз; 96/128 бит пайдаланыңыз.
5) Индекстер, ыстық беттер және сақтау
Кездейсоқ кілттер (v4) кірістірмелерді индекстің ағаш бойынша біркелкі үлестіреді → «құйрығы» жоқ, бірақ кэш-орналасуы нашар.
Уақыт бойынша сұрыпталатындар (v7/ULID/Snowflake) «артқы жағына» → ең жақсы орналасуы мен компрессиясы, бірақ жоғары параллель жазбаның астындағы ыстық беттердің қаупі қойылады.
- tenant/region бойынша префикстер/шардинг (уақыт алдында 1-2 байт қосу);
- interleaving: үлкен биттердегі кездейсоқтық бөлігі;
- батч-ендірмелер, B-ағашындағы fillfactor, BRIN-ге автоөткел/үлкен логтар үшін кластерлеу.
- 'UUID (16B)' vs 'BIGINT (8B) '/' INT8' жад/кэшті үнемдейді; Base32/58/64 жолдары өлшемін 20-60% ұлғайтады. ДБ үшін бинарлық сақтаңыз, жиегіндегі жолға сериалдаңыз.
6) Қауіпсіздік және құпиялылық
SEQUENCE/INT URL/API-дегі көпшілік ID ретінде пайдаланбаңыз: болжамды → ресурстарды тізімдеу.
Сыртқы сілтемелер үшін рандомды, болжанбайтын ID (v4/v7/ULID/KSUID) қосыңыз.
PII-ді ID-ге кодтамаңыз. Егер төлсипатты қосу керек болса, шифрлаңыз/қол қойыңыз (мысалы, JWE/JWS) немесе мөлдір емес белгілерді пайдаланыңыз.
URL қауіпсіз кодталуы: Base32 Crockford, Base58 ('0OIl' жоқ), Base64url.
7) Мульти-теңдік, префикстер және бағыттау
Пішім: '[TENANT _ PREFIX] - [ID]' немесе бинарлық: 'tenant _ id | | id'.
Артықшылықтары: жалға алушы бойынша жылдам сүзгілер/партиялар, N + 1 сканнен қорғау.
Минустар: жоғары биттердегі энтропия тығыздығын нашарлатуы мүмкін → бөлуді ойластырыңыз (префикс хеш).
Hash-суффикс (2-3 байт) коллизияларды азайтады және shard-роутингке көмектеседі: 'shard = hash (id)% N'.
8) Таңдау бойынша практикалық ұсынымдар
API, жария сілтемелер, қатаң тәртіпсіз бөлінген сервистер: UUIDv4, ULID/KSUID.
Уақыт бойынша жиі сұрыптайтын логи/оқиғалар/тапсырыстар: UUIDv7 немесе ULID (монотонды).
Жергілікті монотонды және қысқа кілті бар аса жоғары өткізу: Snowflake-ұқсас 64-бит (уақыт тәртібі талап етіледі).
Артефактілерді/билдтерді/блобтарды сақтау орындары: мекен-жайлық контент (SHA-256), ал үстіңгі жағы - адам-достық қысқа «витрина» (Hashids/сілтеме).
Бір ДҚ-дағы жергілікті кестелер: SEQUENCE/IDENTITY + ашық сілтемелер үшін сыртқы «орау» (masking).
9) Іске асыру және мысалдар
9. 1 PostgreSQL
UUID-ді бинарлық түрде сақтаңыз, индекстер - 'btree' немесе 'hash'.
sql
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE TABLE orders (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(), -- или uuid_generate_v4()
created_at timestamptz NOT NULL DEFAULT now(),
tenant smallint NOT NULL
);
-- For time-sortable (UUIDv7) store binary (uuid), generation in the application.
-- If you want a cluster by time:
CREATE INDEX ON orders (created_at DESC);
Sequential hot fix: time-sorted ID үшін үлкен биттерге «тұз» қосыңыз немесе tenant бойынша партиялаңыз:
sql
CREATE TABLE orders_t1 PARTITION OF orders FOR VALUES IN (1);
CREATE TABLE orders_t2 PARTITION OF orders FOR VALUES IN (2);
9. 2 Redis (атомарлық есептеуіштер/монутония)
bash
INCR "seq: orders" # local sequence combine: epoch_ms<<20 (worker_id<<10) (seq & 1023)
9. 3 Snowflake-ұқсас генератор (жалған код)
pseudo const EPOCH = 1704067200000 # custom epoch (ms)
state: last_ms=0, seq=0, worker=7, region=3
next():
now = epoch_ms()
if now < last_ms: wait_until(last_ms) # защита от clock back if now == last_ms:
seq = (seq + 1) & ((1<<12)-1) # 12 бит if seq == 0: wait_next_ms()
else:
seq = 0 last_ms = now return (now-EPOCH)<<22 region<<17 worker<<12 seq
9. 4 ULID/UUID қосымшаларда
Go
go
// ULID t:= time. Now(). UTC()
entropy:= ulid. Monotonic(rand. New(rand. NewSource(t. UnixNano())), 0)
id:= ulid. MustNew(ulid. Timestamp(t), entropy)
//UUID v7 (if there is a library)
id:= uuid. Must(uuid. NewV7())
Node. js
js import { ulid } from 'ulid';
import { v4 as uuidv4 } from 'uuid';
const id1 = ulid();
const id2 = uuidv4(); // v4
Python
python import uuid, time id_v4 = uuid. uuid4()
For v7, use a library (for example, uuid6/7 third-party packages)
10) Кодтау және ұсыну
ДБ-да бинарлық ('BYTEA', 'UUID') → ықшам және жылдам. Шетінде мыналарға түрлендіріңіз:- Crockford (ULID) Base32: көзбен шолып ұқсас таңбаларсыз, регистрге сезімтал емес.
- Base58: қысқаша Base32/64 адам оқитын токендер үшін, URL-safe.
- Base64url: қысқа, бірақ '-' және '_' URL.
Жолдарды салыстыру кезінде көшірмелерді болдырмау үшін регистрді және пішімді (дефистер/олардың болмауы) тұрақтандырыңыз.
11) Тест-плейбуктер және бақылау
Қайшылықтар: 'id _ collision _ total' метрикасы (0 болуы тиіс),> 0 кезінде алерт.
Префикстерді бөлу: аға байттардың гистограммасы - сатып алуды іздейміз.
Генерациялау жылдамдығы: 'ids _ per _ sec', генератор жасырындылығының p99.
Clock skew (Snowflake үшін): тораптар офсеті, «clock went back» оқиғалары.
Индекстік қалдықтар: p95/p99 'INSERT' latency; блоктау/ыстық беттердің үлесі.
- Инжект «clock drift/back» → генератор күтуде/ауысуда екеніне көз жеткізіңіз.
- Миллисекундта 'sequence' толуы → күтуді тексеру next_ms.
- Жаппай параллелизм → индексінде бұғаттау дауылдары жоқ па.
12) Қарсы үлгілер
AUTO_INCREMENT/SEQUENCE жария ID ретінде: болжау, жылыстау. Ішкі үстінен ашық емес ID пайдаланыңыз.
Сыртқа UUIDv1 (МАС/уақыт): жекелік.
Триллиондаған жазбаға 64-бит кездейсоқ ID: коллизиялардың нақты қаупі.
HA: SPOF жоқ жаһандық «орталық генератор» және тар орын.
clock back қорғаусыз Time-sorted IDs: қайталау/регресс тәртібі.
Ашық нұсқасыз/префикссіз түрлі ID пішімдерін араластыру → Дебаг/көші-қондағы хаос.
Идентификаторды түрлі тіркелгілері/пішіндері бар жолдар ретінде сақтау → жасырын көшірмелер.
13) Енгізу чек-парағы
- Домендік талаптар үшін пішім (v4/v7/ULID/KSUID/Snowflake/SEQ/hash) таңдалды.
- Тәртіпке қойылатын талаптар айқындалды (сұрыпталуы қажет пе).
- Коллизиялар ықтималдығы бағаланды (b бит, n генерациялар) және тәуекел шегі берілді.
- Кодтау жобаланған (БД-да бинарлық + адам оқитын витрина).
- time-sorted үшін - clock back, sequence-лимиттер және NTP/PTP тәртіптен қорғау.
- Көпшілік ID үшін - болжауға келмеушілік (рандом/ULID/KSUID), PII болмауы.
- Шард-роутинг (hash (id)% N), мульти-тенантты префикстер ойластырылған.
- Бақылау қабілеті: коллизиялар, бөлу, кідірістер, clock skew.
- Sequence/жоғары бәсекелестік/терезе ұзындығына арналған тест-кейстер.
- Формат, нұсқа, дәуір, биттік белгілеу құжаттамасы және көші-қон жоспары.
14) FAQ
Q: Микросервистер үшін «әдепкі» не таңдау керек?
A: UUIDv7 немесе ULID: уақыт реттелуі, көп энтропия, шетінде қарапайым генерация. Сыртқы API үшін - ULID/UUIDv4 да.
Q: Қысқа және адам оқитын ID қажет.
A: ULID/KSUID немесе Base58-кодтау 128-бит кездейсоқ/уақытша ID. Ұзындығы мен қайшылықтарын есте сақтаңыз.
Q: «Қысқа сандық» ID жасауға бола ма, бірақ қауіпсіз?
A: Иә: ішкі SEQ сақтаңыз, ал сыртқа opaque токенін (96-128 бит рандпен) немесе Hashids тұзбен + қолтаңбаны беріңіз.
Q: SEQ-ден UUIDv7-ге қалай көшуге болады?
A: Жаңа 'id _ new' (UUID) бағанын енгізіңіз, екі рет басып шығарыңыз, жаңа ID сілтемелерін жариялаңыз, содан кейін РК/сыртқы кілттерді ауыстырыңыз және ескісін жойыңыз.
Q: Неге менің ULID ендірмелерім «ыстық» болды?
А: Қатаң өсетін кілттерді бір индекске енгізесіз. / tenant партияларына бөліп, үлкен биттерді араластырыңыз, batch-ендірмелерді пайдаланыңыз.
15) Қорытынды
Жақсы ID - бұл міндетке арналған қасиеттердің дұрыс жиынтығы: жеткілікті энтропия, болжамды сұрыптау (егер қажет болса), қауіпсіз жариялылық және индекстерді дұрыс пайдалану. Қарапайымдылық пен таратылу үшін UUIDv4/ULID/UUIDv7/KSUID, тығыз монотония мен қысқа кілттер үшін Snowflake (уақыт тәртібінде), жергілікті кестелер үшін бірізділікті, артефактілер үшін контент хэштерін таңдаңыз. Бақылау мен тесттерді енгізіңіз - идентификаторлар тосын сый көзі болмайды.