Идентификаторлорду түзүү
1) Эмне үчүн идентификаторлорго көңүл буруу
ID (ID) - маңыздын негизги ачкычы: БД саптары, билдирүүлөр, файл, заказ. Анын касиеттери көз каранды:- Уникалдуулук жана масштаб (коллизиялар, горизонталдык өсүү).
- Тартиби жана сорттоо (убактылуу корреляция, репликация, дедуп).
- Сактоо өндүрүмдүүлүгү (индекстер, ысык барактар, ачкычтын өлчөмү).
- Коопсуздук (күтүүсүздүк, агып чыгуу, болжолдоо).
- Колдонмо/интеграция (кыска, URL-safe, регистр сезгич эмес).
ID тандоосу - энтропия, тартипке келтирүү, узундук, генерация ылдамдыгы жана эксплуатация ортосундагы компромисс.
2) Негизги талаптар жана терминдер
Уникалдуулук: кагылышуу ыктымалдыгы алгылыктуу тобокелдиктен төмөн болушу керек.
Энтропия: "канча кокустук" ID (бит) бар.
Тартипке келтирүү (time-sortable/k-sortable): лексикографиялык сорттоо ≈ убакыт боюнча сорттоо.
Монотония: түйүн/агымдын ичиндеги тынымсыз ырааттуулук.
Жазуунун локалдуулугу: Жаңы киргизүү индекстин "куйругунда" канчалык топтолгон (ысык барактардын коркунучу).
Алдын ала айтуу: кошуна ID (коопсуздук/API үчүн маанилүү) болжолдоого болобу.
Өкүлчүлүк: бинардык/сап, Base16/32/36/58/64, сызыктар, регистр.
3) Идентификаторлордун негизги үй-бүлөлөрү
3. 1 UUID
v4 (random): 122 entropia бит. Тартипсиз, коопсуздук жана жөнөкөйлүк үчүн жакшы. Минус: "башаламан" индекстер, анткени кокусунан бөлүштүрүү - бирок, бирдей жүктөрдү таркатып, "ысык барактарды" алып салат.
v1 (убакыт + MAC): тартипке келтирүү, бирок МАС/убакыт (купуялык) алып келет; көп учурда качышат.
v7 (time-ordered): миллисекунддук убакыт + рандом бөлүгү. DD убакыт жана жакшы кысуу боюнча лексикографиялык сорттоо боюнча дизайн. Компромисс: индекстин "ысык куйругу" пайда болот; шардана/префикс/инкремент менен дарыланат.
Кеңештер
Тышкы API жана катуу эмес тартип талаптары үчүн - v4.
Окуя/логикалык DD жана "сорттоочу" ачкычтар үчүн - v7.
3. 2 ULID (Crockford Base32)
128 бит: 48 бит убакыт (ms) + 80 бит кокустук. Лексикографиялык убакыт, адам-достук (жок 'I, L, O, U'), URL-safe. Монотондук вариация бар (бирдей убакыт белгиси менен кокустук бөлүгү көбөйөт).
Артыкчылыктары: окулуучулук, тартиптүү, чыдамкайлык.
Кемчиликтери: бир учурда өтө жогорку киргизүү жыштыгы менен - "ысык куйрук".
3. 3 KSUID
160 бит: 32 бит убакыт (сек) дооруна салыштырмалуу + 128 бит кокустук. Көбүрөөк убакыт диапазону жана туруктуу сорттоо, сызыктар ULID кыска? (жок - узун, бирок коддоо менен), бөлүштүрүлгөн логдор жана объекттер үчүн жакшы.
3. 4 Snowflake окшош (k-sortable flake ID)
Классикалык схема (ылайыкташтырылган):
[ timestamp bits ][ region/datacenter bits ][ worker bits ][ sequence bits ]
Касиеттери: бирдикте монотондук өсүү, квази-глобалдуу уникалдуулук, кыска (64 бит) бинардык аткаруу.
Тобокелдик: саатка көз карандылык (дрейф/регресс убактысы), бир тикеде sequence түгөнүп, аймактын/жумушчу биттерин координациялоо.
Дарыланат: "саат артка" коргоо, sequence камдык, убакыт Detector, PTP/NTP тартип.
3. 5 DD ырааттуулугу (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: жогорку биттерде кокустуктун бир бөлүгү;
- батч-inserts, B-жыгач fillfactor, BRIN/Big Logs үчүн кластерлештирүү боюнча auto өткөөл.
- 'UUID (16B)' vs 'BIGINT (8B) '/' INT8' эс/кэш үнөмдөйт; Base32/58/64 саптары өлчөмүн 20-60% га көбөйтөт. DD үчүн бинардык сактоо, четинде бир катар.
6) Коопсуздук жана купуялык
URL/API коомдук ID катары SEQUENCE/INT колдонбогула: болжолдонгон → ресурстарды которуу.
Тышкы шилтемелер үчүн рандомдук, күтүүсүз 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 (monoton).
Жергиликтүү монотондук жана кыска ачкыч менен өтө жогорку өткөрүү: Snowflake сыяктуу 64-бит (убакыт тартиби талап кылынат).
Артефакттарды/имараттарды/блобдорду сактоо: мазмун даректүү (SHA-256), жана үстү - адам-достук кыска "витрина" (Hashids/шилтеме).
бир DD жергиликтүү таблицалар: 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 окшош генератор (psevdocode)
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) Коддоолор жана сунуштар
Бинардык DD ('BYTEA', 'UUID') → компакт жана тез. Чет конверт:- Base32 Crockford (ULID): эч кандай визуалдык окшош белгилер, регистр сезимтал.
- Base58: кыскача Base32/64 адам окуган токендер үчүн, URL-safe.
- Base64url: кыска, бирок '-' жана '_' URL.
Каттын жана форматын турукташтырыңыз (сызыктар/алардын жоктугу), жолдорду салыштырууда дубликаттарды болтурбоо үчүн.
11) Test Playbook жана байкоо
Карама-каршылыктар: метрика 'id _ collision _ total' (0 болушу керек),> 0.
Префикстерди бөлүштүрүү: улук байттардын гистограммасы - сатып алууну издейбиз.
Генерациялоо ылдамдыгы: 'ids _ per _ sec', p99 генератордун жашыруун.
Clock skew (Snowflake үчүн): түйүндөрдүн офсети, "clock went back" окуялары.
Индекс куйруктары: p95/p99 'INSERT' latency; блоктордун/ысык беттердин үлүшү.
- Enject "clock drift/back" → генератор күтүп/которулат деп ишенебиз.
- миллисекундда 'sequence' толуп → күтүү текшерүү next_ms.
- Массалык параллелизм → индексте бөгөттөө бороон-чапкын жок.
12) Анти-үлгүлөрү
AUTO_INCREMENT/SEQUENCE коомдук ID катары: болжолдонууда, агып. ички үстүнөн ачык эмес ID колдонуу.
UUIDv1 (МАС/убакыт) сыртка: купуялык.
триллиондогон жазуулар үчүн 64-бит кокустук ID: чыр-чатактын реалдуу коркунучу.
Global "борбордук генератор" жок HA: SPOF жана тар жер.
Time-sorted IDs clock back коргоосуз: кайталанма/regress тартиби.
Ачык версия/префикс жок ар кандай ID форматтарын аралаштыруу → Дебагда/миграцияда башаламандык.
Ар кандай регистрлер/формалар менен саптар катары ID сактоо → жашыруун дубликаттар.
13) Киргизүү чек-тизмеси
- Тандалган формат (v4/v7/ULID/KSUID/Snowflake/SEQ/hash) домендик талаптарга ылайык.
- Тартипке карата талаптар аныкталган (сорттоо керекпи).
- Коллизия ыктымалдыгы бааланган (b бит, n генерация) жана тобокелдик чеги белгиленген.
- Коддоо иштелип чыккан (бинардык DD + адам окуган дисплей).
- Time-sorted үчүн - clock back коргоо, sequence-лимиттери жана NTP/PTP тартип.
- коомдук ID үчүн - күтүүсүздүк (Rand/ULID/KSUID), PII жоктугу.
- Шард-роутинг (hash (id)% N), көп тенанттык префикстер ойлонулган.
- байкоо: карама-каршылыктар, бөлүштүрүү, кечигүү, clock skew.
- Sequence/жогорку атаандаштык/терезе узундугу толуп сыноо учурлары.
- Документ форматы, версия, доор, бит белгилөө жана миграция планы.
14) FAQ
Q: микросервистер үчүн "демейки" эмнени тандоо керек?
A: UUIDv7 же ULID: убакыт тартиби, entropy көп, четинде жөнөкөй муун. Тышкы API үчүн - ULID/UUIDv4 да оку.
Q: Биз кыска жана адам окуган ID керек.
A: ULID/KSUID же Base58-коддоо 128-бит кокустук/убактылуу ID. узундугу жана чыр-чатактар жөнүндө унутпа.
Q: "кыска сандык" ID жасоого болот, бирок коопсуз?
A: Ооба: ички SEQ сактоо жана opaque токен (96-128 бит rand) же туз + кол менен Hashids берет.
Q: UUIDv7 SEQ менен көчүп кантип?
A: Жаңы тилкени киргизиңиз 'id _ new' (UUID), кош, жаңы ID шилтемелерди жарыялоо, андан кийин РК/тышкы ачкычтарды которуу жана эскисин алып салуу.
Q: Эмне үчүн менин ULID кошумчалары "ысык" болуп калды?
A: Бир индекске катуу өсүп ачкычтарды киргизүү. партияларга/tenant майдалап, улук биттерин аралаштырып, батч-кошумчаларды колдонуңуз.
15) натыйжалары
Жакшы ID милдет үчүн туура касиеттердин топтому болуп саналат: жетиштүү entropy, алдын ала сорттоо (керек болсо), коопсуз коомдук жана дени сак индекстерди пайдалануу. жөнөкөй жана бөлүштүрүү үчүн UUIDv4/ULID/UUIDv7/KSUID тандоо, Snowflake - тыгыз монотония жана кыска ачкычтар үчүн (убакыт тартиби менен), ырааттуулук - жергиликтүү таблицалар үчүн, мазмун хэш - артефакттар үчүн. Байкоо жана тесттерди коюңуз - жана идентификаторлор сюрприздердин булагы болбой калат.