GH GambleHub

ID-uri generatoare

1) De ce să acordați atenție identificatorilor

Identificator (ID) - cheia fundamentală a entității: linii de bază de date, mesaje, fișier, ordine. Proprietățile sale depind de:
  • Unicitate și scară (coliziuni, creștere orizontală).
  • Ordine și sortare (corelație timp, replicare, dedup).
  • Performanță de stocare (indici, pagini fierbinți, dimensiune cheie).
  • Siguranță (imprevizibilitate, scurgeri, ghicit).
  • Usability/integration (scurt, URL-safe, nu sensibil la caz).

Alegerea ID-ului este un compromis între entropie, ordonabilitate, lungime, rata de generare și exploatare.

2) Cerințe cheie și termeni

Unicitate: probabilitatea de coliziune trebuie să fie mai mică decât riscul acceptabil.
Entropia: „câtă aleatorie” conține ID (bit).
Sortare temporală/k-sortabilă-lexicografică ≈ pe bază de timp.
Monotonia: o secvență care nu scade într-un nod/flux.
Localitatea de intrare: cât de mult este concentrată noua inserție în „coada” indexului (pericolul paginilor fierbinți).
Predictibilitate: Este posibil să se ghicească ID-urile vecine (importante pentru securitate/API).
Reprezentare: binar/string, Base16/32/36/58/64, cratime, caz.

3) Familii majore de identificare

3. 1 UUID

v4 (aleatoriu): 122 biți de entropie. Dezordonat, bun pentru siguranță și simplitate. Minus: indicii „haotici” din cauza distribuției aleatorii - care, totuși, disipează uniform încărcăturile și elimină „paginile fierbinți”.
v1 (timp + MAC): aranjează, dar poartă MAC/timp (confidențialitate); adesea evitată.
v7 (timp comandat): timp de milisecunde + part.proiectare aleatoare pentru sortare lexicografică în funcție de timp și compresie bună în baza de date. Compromis: Apare „coada fierbinte” a indicelui; tratate prin shardening/prefixe/increment.

Sfaturi

Pentru API-uri externe și cerințe de comandă laxă - v4.
Pentru bazele de date eveniment/jurnal și cheile „sortate” - v7.

3. 2 ULID (Crockford Base32)

128 biți: 48 biți de timp (ms) + 80 biți de aleatoriu. Lexicografic sortate după timp, om-friendly (fără „I, L, O, U”), URL-safe. Există o variație monotonă (cu aceeași ștampilă de timp, partea aleatorie crește).
Pro: lizibilitate, ordonabilitate, portabilitate.
Contra: cu o frecvență foarte mare de inserții la un moment dat - „coada fierbinte”.

3. 3 KSUID

160 biți: 32 biți de timp (sec) în raport cu epoca + 128 biți de aleatorii. Interval de timp mai mare și sortare stabilă, șiruri mai scurte decât ULID? (nu - mai, dar cu propria codificare), bun pentru jurnalele distribuite și obiecte.

3. 4 ID-uri cu fulgi de nea (k-sortabile)

Schema clasică (personalizată):

[ timestamp bits ][ region/datacenter bits ][ worker bits ][ sequence bits ]

Proprietăți: creștere monotonă pe un nod, unicitate cvasi-globală, reprezentare binară scurtă (64 biți).
Riscuri: dependență de ceas (timp în derivă/regresie), epuizarea secvenței într-o singură căpușă, coordonarea regiunii/biți de lucrător.
Tratat: protecție împotriva „ceasului înapoi”, secvență de rezervă, detector de timp, disciplină PTP/NTP.

3. 5 secvenţe DB (SECVENŢĂ/IDENTITATE)

Cea mai simplă generație monotonă într-un singur DBMS/ciob.
Pro: scurt, rapid, convenabil pentru mesele locale.
Contra: dificil la nivel global într-un cluster distribuit; previzibil (nesigur ca o cheie publică), creează o coadă fierbinte a indicelui.

3. 6 ID-uri de adrese de conținut (conținut hash)

Conținut SHA-256/Blake3 → ID stabil, eliminarea duplicatelor, verificarea integrității, caching.
Pro: determinism, protecție împotriva substituției.
Contra: generație scumpă (CPU), coliziunile sunt zerouri practice, sortare fără timp, lungime.

4) Coliziuni și „paradoxul zilei de naștere” (intuitiv)

Probabilitatea de coliziune pentru un ID aleatoriu al generațiilor size 'b' bits at 'n' este de aproximativ:

p ≈ 1 - exp (-n (n-1 )/2/2 ^ b) ≈ n ^ 2/2 ^ (b + 1) (for small p)
Exemple:
  • UUIDv4 (122 biți) la n = 10 ^ 12 (trilioane) → p ~ 1e-14 (neglijabil).
  • 64-bit → aleatoare cu n = 10 ^ 9 deja p ~ 0. 027 (risc notabil).
  • Concluzie: 64-bit aleatoare nu este de multe ori suficient pentru sisteme uriașe; utilizați 96/128 biți.

5) Indici, pagini fierbinți și stocare

Cheile aleatorii (v4) distribuie uniform inserțiile în arborele index → nu există „coadă”, dar localitatea cache este mai rea.
Sortarea în timp (v7/ULID/Snowflake) se introduce „în coadă” → o mai bună localitate și compresie, dar riscul de pagini fierbinți sub înregistrare paralelă ridicată.

Atenuarea caldă a cozii:
  • prefixe/împărțire în funcție de chiriaș/regiune (adăugați 1-2 octeți înainte de timp);
  • interleaving: o parte a aleatorii în biți mai mari;
  • inserții de lot, fillfactor în arborele B, auto-tranziție la BRIN/grupare pentru jurnalele mari.
Dimensiunea este importantă:
  • „UUID (16B)” vs „BIGINT (8B) ”/„ INT8” salvează memoria/memoria cache; rândurile Base32/58/64 cresc dimensiunea cu 20-60%. Pentru baza de date, stocați binar, serializați la un șir de caractere pe margine.

6) Securitate și confidențialitate

Nu utilizați SEQUENCE/INT ca ID-uri publice în URL/API: enumerarea → a resurselor.
Adăugați ID-uri aleatorii, imprevizibile (v4/v7/ULID/KSUID) pentru referințe externe.
Nu codificați PII în ID. Dacă doriți să activați atributul, să criptați/semnați (de exemplu, JWE/JWS) sau să utilizați jetoane opace.
Codări URL-safe: Base32 Crockford, Base58 (fără „0OI”), Base64url.

7) Multi-chirie, prefixe și rutare

Format: '[TENANT _ PREFIX] - [ID]' sau binar: 'tenant _ id | | id'.
Pro: filtre rapide/petreceri chiriași, protecție împotriva scanărilor N + 1.
Contra: poate agrava densitatea entropiei în biții mai mari → ia în considerare distribuția (prefixul hash).
Sufixul hash (2-3 octeți) reduce coliziunile și ajută la rutarea cioburilor: 'shard = hash (id)% N'.

8) Recomandări practice pentru selecție

API, link-uri publice, servicii distribuite fără ordine strictă: UUIDv4, ULID/KSUID.
Jurnale/evenimente/comenzi, unde deseori sortăm după timp: UUIDv7 sau ULID (monoton).
Lățime de bandă ultra-mare cu monotonie locală și cheie scurtă: 64 de biți asemănători fulgilor de zăpadă (este necesară disciplina de timp).
Seifuri de artefacte/builds/blobs: conținut-adresabil (SHA-256), și pe partea de sus - un om-friendly scurt „vitrina” (Hashids/link).
Tabele locale într-o bază de date: SECVENȚĂ/IDENTITATE + „înveliș” extern pentru legături publice (mascare).

9) Implementări și exemple

9. 1 PostgreSQL

Stocați UUID binar, indici - „btree” sau „hash” după cum este necesar.

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);
Fixarea fierbinte secvențială: pentru ID-ul sortat în timp, adăugați „sare” la biții superioare sau scorul de chiriaș:
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 (contoare atomice/monutonie)

bash
INCR "seq: orders" # local sequence combine: epoch_ms<<20     (worker_id<<10)      (seq & 1023)

9. 3 Generator asemănător fulgilor de nea (pseudocod)

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 în aplicaţii

Du-te

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())

Nod. 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) Codificări și reprezentări

Binar în baza de date („BYTEA”, „UUID”) → compact și rapid. La margine, convertiți la:
  • Base32 Crockford (ULID): caz insensibil, fără caractere similare din punct de vedere vizual.
  • Base58: pe scurt Base32/64 pentru jetoane care pot fi citite de om, URL-safe.
  • Base64url: scurt, dar „-” și „_” în URL.

Stabilizați cazul și formatul (cratime/nici una) pentru a evita duplicatele atunci când comparați șiruri.

11) Cărți de joc de testare și observabilitate

Coliziuni: metric 'id _ collision _ total' (trebuie să fie 0), alertă la> 0.
Distribuția prefixului: histogramă de octeți înalți - căutăm cumpărarea.
Rata de generare: 'ids _ per _ sec', latența generatorului p99.
Ceas înclinare (pentru fulg de zăpadă): offset noduri, "ceas' evenimente.
Cozi index: p95/p99 „INSERT” latență; proporția de încuietori/pagini fierbinți.

Ziua jocului:
  • Injecție „ceas derivă/înapoi” → asigurați-vă că generatorul este în așteptare/comutare.
  • „equence” se revarsă în milisecunde → next_ms verificare de așteptare.
  • Paralelismul de masă → dacă există furtuni de încuietori în index.

12) Anti-modele

AUTO_INCREMENT/SEQUENCE ca un ID public: ghicit, scurgeri. Utilizați un ID public opac peste unul intern.
UUIDv1 (MAC/time) afară: intimitate.
ID-ul aleator pe 64 de biți per trilion de intrări: risc real de coliziuni.
Global „generator central” fără HA: SPOF și blocaj.
ID-uri sortate în timp fără protecție împotriva ceasului: duplicate/regresie a comenzii.
Amestecarea diferitelor formate de ID fără o versiune explicită/prefix → haos în dezbatere/migrații.
Salvarea ID-ului ca șir cu diferite registre/forme → duplicate ascunse.

13) Lista de verificare a implementării

  • Formatul selectat (v4/v7/ULID/KSUID/Snowflake/SEQ/hash) pentru cerințele de domeniu.
  • Cerințe de comandă definite (dacă sortabilitatea este necesară).
  • Probabilitatea de coliziuni (b biți, n generații) este estimată și pragul de risc este stabilit.
  • Codificarea este proiectată (binară în caseta de prezentare DB + care poate fi citită de om).
  • Pentru sortarea timpului - protecția ceasului înapoi, limitele de secvență și disciplina NTP/PTP.
  • Pentru ID-uri publice - imprevizibilitate (aleatoriu/ULID/KSUID), absența PII.
  • Gândit hash (id)% N, prefixe multi-chiriaș.
  • Observabilitate: coliziune, distribuție, latență, măsurători de înclinare a ceasului.
  • Secvență/Contention/Fereastra Lungime Overflow Cazuri de testare.
  • Format, versiune, epocă, bitmap, și documentația planului de migrare.

14) ÎNTREBĂRI FRECVENTE

Î: Ce să alegeți „implicit” pentru microservicii?
R: UUIDv7 sau ULID: comandă de timp, multă entropie, generație simplă la margine. Pentru API-urile externe, ULID/UUIDv4 este de asemenea de aprox.

Î: Aveți nevoie de un ID scurt și ușor de citit.
R: ULID/KSUID sau Base58-128-bit codare ID aleatorie/temporară. Amintiți-vă despre lungime și coliziuni.

Î: Este posibil să se facă ID-uri „scurte numerice”, dar sigure?
R: Da: stocați SEQ-ul intern, iar în exterior dați jetonul opac (96-128 biți aleatori) sau Hashids cu semnătură sare +.

Î: Cum migrez de la SEQ la UUIDv7?
R: Introduceți o nouă coloană 'id _ new' (UUID), două căi, publicați referințe la noul ID, apoi comutați tastele DC/străine și ștergeți-l pe cel vechi.

Î: De ce inserțiile mele ULID au devenit „fierbinți”?
R: Introduceți cheile care cresc strict într-un singur indice. Partiție/chiriaș, se amestecă biți de înaltă comandă, utilizați inserții de lot.

15) Totaluri

Un ID bun este setul corect de proprietăți pentru problemă: suficientă entropie, sortare previzibilă (dacă este necesar), publicitate sigură și exploatarea sănătoasă a indicilor. Alegeți UUIDv4/ULID/UUIDv7/KSUID pentru simplitate și distribuție, Fulg de zăpadă pentru monotonie densă și chei scurte (pentru disciplina de timp), secvențe pentru tabele locale, hash-uri de conținut pentru artefacte. Stabiliți observabilitatea și testele - iar identificatorii vor înceta să mai fie o sursă de surprize.

Contact

Contactați-ne

Scrieți-ne pentru orice întrebare sau solicitare de suport.Suntem mereu gata să ajutăm!

Telegram
@Gamble_GC
Pornește integrarea

Email-ul este obligatoriu. Telegram sau WhatsApp sunt opționale.

Numele dumneavoastră opțional
Email opțional
Subiect opțional
Mesaj opțional
Telegram opțional
@
Dacă indicați Telegram — vă vom răspunde și acolo, pe lângă Email.
WhatsApp opțional
Format: cod de țară și număr (de exemplu, +40XXXXXXXXX).

Apăsând butonul, sunteți de acord cu prelucrarea datelor dumneavoastră.