logo hsb.horse
← Voltar para o índice do blog

Blog

Guia de implementação UUID v7: Crie com JavaScript, Go e Shell

A estrutura de bits do UUID v7, configurações de bits de versão/variante, implementação mínima em JavaScript, Go e Shell, itens de verificação durante a implementação e referências RFC são organizadas em uma página. Um guia prático que resume os pontos a serem verificados na lógica de geração para desenvolvedores que desejam introduzir IDs com segurança e fáceis de classificar em séries temporais. Pode ser usado para confirmação antes da implementação.

Publicado: Atualizado:

Resumiremos apenas os pontos essenciais necessários ao implementar o UUID v7.
Neste artigo, você pode verificar a estrutura de bits do UUID v7, como definir a versão/variante e a implementação mínima em JavaScript, Go e Shell.

Fundamentos do UUID v7

O UUID v7 tem 128 bits com um carimbo de data/hora em milissegundos no início.

CampoNúmero de bitsFunção
timestamp48Tempo Unix (ms)
ver40111 (v7)
rand_a12Valor aleatório
var210 (variante)
rand_b62Valor aleatório

Com esta configuração é possível criar IDs que geralmente são fáceis de ordenar por ordem de tempo de geração.

Etapas comuns durante a implementação

  1. Primeiro, preencha 16 bytes com números aleatórios
  2. Substitua os primeiros 6 bytes pela hora atual (milissegundos)
  3. Defina 0x7 (versão) nos 4 bits superiores de value[6]
  4. Defina 10 (variante) para os 2 bits superiores de value[8]

Exemplo de implementação de JavaScript/TypeScript

function uuidV7Bytes(): Uint8Array {
const value = new Uint8Array(16);
crypto.getRandomValues(value);
const timestamp = BigInt(Date.now());
value[0] = Number((timestamp >> 40n) & 0xffn);
value[1] = Number((timestamp >> 32n) & 0xffn);
value[2] = Number((timestamp >> 24n) & 0xffn);
value[3] = Number((timestamp >> 16n) & 0xffn);
value[4] = Number((timestamp >> 8n) & 0xffn);
value[5] = Number(timestamp & 0xffn);
value[6] = (value[6] & 0x0f) | 0x70;
value[8] = (value[8] & 0x3f) | 0x80;
return value;
}

Exemplo de implementação Go

package main
import (
"crypto/rand"
"fmt"
"time"
)
func uuidV7() ([16]byte, error) {
var value [16]byte
if _, err := rand.Read(value[:]); err != nil {
return value, err
}
timestamp := uint64(time.Now().UnixMilli())
value[0] = byte(timestamp >> 40)
value[1] = byte(timestamp >> 32)
value[2] = byte(timestamp >> 24)
value[3] = byte(timestamp >> 16)
value[4] = byte(timestamp >> 8)
value[5] = byte(timestamp)
value[6] = (value[6] & 0x0F) | 0x70
value[8] = (value[8] & 0x3F) | 0x80
return value, nil
}
func main() {
id, _ := uuidV7()
fmt.Printf("%x\n", id)
}

Exemplo de implementação de Shell Script

#!/bin/sh
uuid_v7() {
timestamp=$(date +%s)000
timestamp_hi=$((timestamp >> 16))
timestamp_lo=$((timestamp & 0xFFFF))
rand_a=0x$(LC_ALL=C tr -dc '0-9a-f' < /dev/urandom | head -c4)
ver_rand_a=$((0x7000 | (0x0FFF & rand_a)))
rand_b_hi=0x$(LC_ALL=C tr -dc '0-9a-f' < /dev/urandom | head -c4)
var_rand_hi=$((0x8000 | (0x3FFF & rand_b_hi)))
rand_b_lo=$(LC_ALL=C tr -dc '0-9a-f' < /dev/urandom | head -c12)
printf "%08x-%04x-%04x-%04x-%s\n" \
"$timestamp_hi" "$timestamp_lo" "$ver_rand_a" "$var_rand_hi" "$rand_b_lo"
}
uuid_v7

POSIX date não pode lidar diretamente com milissegundos, portanto o método de aquisição precisa ser ajustado dependendo do ambiente de implementação.

Itens de verificação de implementação

  • Avalie o risco de colisão ao gerar uma grande quantidade no mesmo milissegundo
  • Padronize o formato (string hifenizada ou 16 bytes) do lado do usuário
  • Decida primeiro a estratégia de índice do banco de dados (suposição de classificação de série temporal)

Materiais de referência (externos)

resumo

A implementação do UUID v7 em qualquer idioma centra-se na “incorporação de carimbo de data/hora + manipulação de bits de versão/variante”.
Dependendo dos seus requisitos, você pode escolher entre usar uma biblioteca existente ou criar uma implementação mínima internamente.