GH GambleHub

Geração de ID

1) Por que prestar atenção aos identificadores

ID é a chave fundamental da entidade: linhas de banco de dados, mensagens, arquivo, encomenda. Suas propriedades dependem:
  • Exclusividade e escala (colisões, crescimento horizontal).
  • Ordem e triagem (correlação temporária, replicação, dedução).
  • Desempenho de armazenamento (índices, páginas quentes, tamanho da chave).
  • Segurança (imprevisível, fuga, adivinhação).
  • Yusabiliti/integração (curto, URL-safe, não sensível a maiúsculas).

A escolha de ID é um compromisso entre entropia, ordenabilidade, comprimento, velocidade de geração e operação.

2) Requisitos e termos essenciais

Única, a probabilidade de conflito deve ser inferior ao risco aceitável.
Entropia: «Quantos acidentes» contém ID (bit).
Ordenabilidade (time-sortable/k-sortable): Ordenação vocabulária ≈ horária.
Monotonia: seqüência não decrescente dentro do nó/fluxo.
Local da gravação: quanto a nova inserção se concentra na «cauda» do índice (perigo de páginas quentes).
Previsividade: você pode adivinhar o ID próximo (importante para a segurança/API).
Apresentação: binário/linha, Base16/32/ 36/58/64, defeitos, maiúsculas.

3) Famílias principais de identificadores

3. 1 UUID

v4 (random): 122 bits de entropia. Desordenado, bom para segurança e simplicidade. Menos: os índices são «caídos» devido à distribuição aleatória - o que, no entanto, dissipa as cargas e remove as «páginas quentes» de forma uniforme.
v1 (time + MAC): organizamos, mas leva MAS/tempo (privacidade); Muitas vezes evitam.
v7 (time-ordered): tempo milissegundo + random. Design sob ordem lexicográfica por tempo e boa compressão em BD. Compromisso: A cauda quente do índice aparece; É tratado com charding/prefixo/encarnação.

Dicas

Para APIs externas e exigências de ordem não altas - v4.
Para BB de evento/laje e chaves «ordenadas» - v7.

3. 2 ULID (Crockford Base32)

128 bits: 48 bits de tempo (ms) + 80 bits de casualidade. Lexicografado por tempo, homem amigável (sem 'I, L, O, U'), URL safe. Há uma variação monótona (com a mesma marca de tempo, a parte aleatória aumenta).
Os benefícios são leitura, ordenabilidade, portabilidade.
Contras: A uma taxa de inserção muito alta em um momento é «cauda quente».

3. 3 KSUID

160 bits: 32 bits de tempo (segundos) em relação à era + 128 bits de casualidade. Maior intervalo de tempo e estabilidade de triagem, linhas ULID mais curta? (não - mais longo, mas com sua codificação), é bom para logs e objetos distribuídos.

3. 4 Snowflake-similares (k-sortable flake IDs)

Padrão clássico (personalizável):

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

Propriedades: crescimento monótono no nó, exclusividade quase global, representação binária curta (64 bits).
Riscos: dependência de relógios (deriva/regressão do tempo), esgotamento sequence em uma única tecla, coordenação de bits region/worker.
Tratamento: proteção contra «clock back», reserva sequence, detector de tempo, PTP/NTP disciplina.

3. 5 Sequências de BD (SEQUENCE/IDENTITY)

Geração monótona mais simples em um DBD/deque.
Benefícios: curto, rápido, conveniente para tabelas locais.
Contras: difícil globalmente em um cluster distribuído; previsivelmente (não seguro como chave pública), cria uma cauda quente de índice.

3. 6 ID de endereço de conteúdo (hash conteúdo)

SHA-256/Blake3 do conteúdo → ID estável, dedução, verificação de integridade, armazenamento em dinheiro.
Mais, determinismo, protecção contra trocas.
Contras: geração cara (CPU), colisões de zeros práticos, sem triagem temporal, comprimento.

4) Conflitos e «aniversário paradoxal» (intuitivo)

A probabilidade de conflito para uma ID aleatória de tamanho 'b' bit 'nas gerações' n 'é próxima:

p ≈ 1 - exp (-n (n-1 )/2/2 ^ b) ≈ n ^ 2/2 ^ (b + 1) (for small p)
Exemplos:
  • UUIDv4 (122 bits) a n = 10 ^ 12 (trilhão) → p £1e-14 (desrespeitado).
  • O rand de 64 bits → a n = 10 ^ 9 já p £0. 027 (risco notável).
  • Conclusão: 64 bits aleatórios muitas vezes são escassos para sistemas enormes; use 96/128 bits.

5) Índices, páginas quentes e armazenamento

As chaves aleatórias (v4) distribuem as inserções de forma uniforme na árvore do índice → não há «cauda», mas são piores do que a localidade em dinheiro.
O tempo de arrumação (v7/ULID/Snowflake) é inserido «na cauda» → melhor localidade e compressão, mas o risco de páginas quentes sob alto registro paralelo.

Amortecer a cauda quente:
  • prefixo/charding por tenant/region (adicionar 1-2 bytes antes do tempo);
  • interleaving: parte do acidente em bits mais velhos;
  • inserção de batch, felfator na árvore B, saída automática em BRIN/clusterização para grandes logs.
O tamanho é importante:
  • 'UUID (16B)' vs 'BIGINT (8B) '/' INT8' economiza memória/dinheiro; as linhas Base32/58/64 aumentam o tamanho entre 20% e 60%. Para um BD, guarde binário, serigrafe em uma linha na borda.

6) Segurança e privacidade

Não use SEQUENCE/INT como ID público no URL/API: adivinhado → alocação de recursos.
Adicione ID random e imprevisível (v4/v7/ULID/KSUID) para links externos.
Não codifique PII no ID. Se você desejar incluir um atributo, criptografe/assine (por exemplo, JWE/JWS) ou use tocadores opacos.
Codificações seguras URL: Base32 Crockford, Base58 (sem '0OIl'), Base64url.

7) Multi-tenência, prefixados e rotação

Formato: '[TENANT _ PREFERIX] - [ID]' ou binário: 'tenant _ id | | id'.
Vantagens: filtros rápidos/partituras por locador, proteção contra N + 1 raias.
Contras: Pode piorar a densidade da entropia nos bits mais velhos → pensar na distribuição (hesh prefixo).
O sufixo hash (2-3 bytes) reduz os conflitos e ajuda o routing shard = hash (id)% N '.

8) Recomendações práticas de escolha

API, links públicos, serviços distribuídos sem ordem máxima: UUIDv4, ULID/KSUID.
Logs/eventos/pedidos, onde muitas vezes ordenamos por tempo, UUIDv7 ou ULID (monótono).
Banda de banda ultrarrápida com monotonia local e chave curta: Snowflake-semelhante a 64 bits (precisa de disciplina de tempo).
Armazéns de artefatos/bildos/blobs: conteúdo-endereçado (SHA-256) e acima de homem-amigável «vitrine» (Hasids/link).
Tabelas locais de um BD: SEQUENCE/IDENTITY + «embrulho» externo para links públicos (masking).

9) Implementações e exemplos

9. 1 PostgreSQL

Guarde o UUID binário, os índices são 'btree' ou 'hash' por necessidade.

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: para time-sorted ID, adicione «sal» em batidas seniores ou particione por 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 (contadores atômicos/monutonia)

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

9. 3 Snowflake-gerador semelhante (pseudocode)

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 em aplicativos

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) Codificações e apresentações

Binário em BD ('BYTEA', 'UUID') → compacto e rápido. Na borda, converta para:
  • Base32 Crockford (ULID): insensível a maiúsculas, sem caracteres visualmente semelhantes.
  • Base58: mais curto que o Base32/64 para tokens humanos, URL-safe.
  • Base64url: curto, mas 'e' _ 'no URL.

Estabilize a maiúscula e o formato (defeitos/ausências) para evitar duplicações na comparação de linhas.

11) Testes playbooks e observação

Conflitos: métrica 'id _ collision _ total' (deve ser 0), alert a> 0.
Distribuição de prefixo: histograma de bytes seniores - Procurando compras.
Taxa de geração: 'ids _ per _ sec', p99 latência do gerador.
Clock skew (para Snowflake): off-set, eventos «clock went back».
Caudas de índice p95/p99 'INSERT' latency; porcentagem de bloqueios/páginas quentes.

Game day:
  • A injecção «clock draft/back» → convencemo-nos de que o gerador está esperando/mudando.
  • Congestionamento de 'sequence' em milissegundos → verificação de espera next _ ms.
  • Paralelismo em massa → se não há tempestades de bloqueio no índice.

12) Anti-pattern

AUTO _ INCREMENT/SEQUENCE como um ID público: adivinhado, vazamento. Use um ID opaco público acima do interno.
UUIDv1 (MAS/tempo) para fora: privacidade.
64 bits de ID aleatório por trilhões de registros, risco real de conflito.
Gerador central global sem HA, SPOF e estreito.
Time-sorted IDs sem proteção contra clock back: duplicados/regredidos de ordem.
Misturar diferentes formatos de ID sem uma versão explícita/prefixo → o caos no debag/migração.
Salvar ID como linhas com diferentes maiúsculas/formas → duplicados ocultos.

13) Folha de cheque de implementação

  • O formato selecionado (v4/v7/ULID/KSUID/Snowflake/SEQ/hash) para os requisitos de domínio.
  • Os requisitos de ordem foram definidos (se a triagem é necessária).
  • A probabilidade de conflito (b bits, n gerações) foi avaliada e um limite de risco foi definido.
  • Codificação projetada (binário em BD + vitrine humana).
  • Para time-sorted - proteção contra clock back, sequence-limite e NTP/PTP disciplina.
  • Para ID público - imprevisibilidade (rand/ULID/KSUID), falta de PII.
  • Traçado shard routing (hash (id)% N), prefixados multi-tenentes.
  • Observabilidade: métricas de conflito, distribuição, atrasos, clock skew.
  • Mala de teste de congestionamento sequence/alta concorrência/comprimento da janela.
  • Documentação de formato, versão, época, marcação de bits e plano de migração.

14) FAQ

Q: O que escolher «padrão» para microsséries?
A: UUIDv7 ou ULID: ordenabilidade em tempo, muita entropia, simples geração na borda. Para API externo - ULID/UUIDv4 também.

Q: Você precisa de um ID curto e humano.
A: ULID/KSUID ou Base58 codificação de 128 bits de ID aleatória/temporária. Lembre-se do comprimento e dos conflitos.

Q: É possível fazer um ID «curto», mas seguro?
A: Sim: guarde o SEQ interno, e dê para fora o token opaque (rand 96-128 bits) ou o Hasids com sal + assinatura.

Q: Como migrar da SEQ para UUIDv7?
A: Digite a nova coluna «id _ new» (UUID), anote-se, publica links para o novo ID, então altere o RC/chaves externas e remova o antigo.

Por que as minhas inserções com a ULID se tornaram quentes?
A: Coloque chaves estritamente crescentes no mesmo índice. Divida em partituras/tenant, misture batidas mais velhas, use inserções batch.

15) Resultado

Uma boa ID é um conjunto correto de propriedades sob a tarefa: entropia suficiente, triagem previsível (se necessário), publicidade segura e exploração saudável de índices. Escolha UUIDv4/ULID/UUIDv7/KSUID para simplicidade e distribuição, Snowflake para monotonia apertada e chaves curtas (com tempo livre), seqüência para tabelas locais, hash conteúdo para artefatos. Coloque a observação e os testes, e os identificadores deixarão de ser uma fonte de surpresas.

Contact

Entrar em contacto

Contacte-nos para qualquer questão ou necessidade de apoio.Estamos sempre prontos para ajudar!

Telegram
@Gamble_GC
Iniciar integração

O Email é obrigatório. Telegram ou WhatsApp — opcionais.

O seu nome opcional
Email opcional
Assunto opcional
Mensagem opcional
Telegram opcional
@
Se indicar Telegram — responderemos também por lá.
WhatsApp opcional
Formato: +indicativo e número (ex.: +351XXXXXXXXX).

Ao clicar, concorda com o tratamento dos seus dados.