logo hsb.horse
← Retour au blog

Blog

Guide d'implémentation de l'UUID v7 : Créer avec JavaScript, Go et Shell

La structure binaire de l'UUID v7, les paramètres binaires de la version/variante, l'implémentation minimale dans JavaScript, Go et Shell, les éléments de vérification lors de l'implémentation et les références RFC sont organisés sur une seule page. Un guide pratique qui résume les points à vérifier dans la logique de génération pour les développeurs qui souhaitent introduire en toute sécurité des identifiants faciles à trier en séries temporelles. Il peut être utilisé pour confirmation avant la mise en œuvre.

Publié: Mis à jour:

Nous résumerons uniquement les points essentiels nécessaires à la mise en œuvre de l’UUID v7.
Dans cet article, vous pouvez vérifier la structure binaire de l’UUID v7, comment définir la version/variante et l’implémentation minimale dans JavaScript, Go et Shell.

L’essentiel de l’UUID v7

L’UUID v7 est de 128 bits avec un horodatage en millisecondes au début.

| Champ | Nombre de bits | Rôle | | --- | --- : | --- | | timestamp | 48 | Temps Unix (ms) | | ver | 4 | 0111 (v7) | | rand_a | 12 | Valeur aléatoire | | var | 2 | 10 (variante) | | rand_b | 62 | Valeur aléatoire |

Avec cette configuration, il est possible de créer des identifiants généralement faciles à trier par ordre de temps de génération.

Étapes courantes lors de la mise en œuvre

  1. Tout d’abord, remplissez 16 octets avec des nombres aléatoires
  2. Écrasez les 6 premiers octets avec l’heure actuelle (millisecondes)
  3. Définissez 0x7 (version) dans les 4 bits supérieurs de value[6]
  4. Réglez 10 (variante) sur les 2 bits supérieurs de value[8]

Exemple d’implémentation 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;
}

Exemple d’implémentation 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)
}

Exemple d’implémentation de script Shell

#!/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 ne peut pas gérer directement les millisecondes, la méthode d’acquisition doit donc être ajustée en fonction de l’environnement d’implémentation.

Éléments de contrôle de mise en œuvre

  • Évaluer le risque de collision lors de la génération d’une grande quantité dans la même milliseconde
  • Standardiser le format (chaîne avec trait d’union ou 16 octets) côté utilisateur
  • Décidez d’abord de la stratégie d’index DB (hypothèse de tri des séries chronologiques)

Liens connexes (à l’intérieur du site)

Documents de référence (externes)

résumé

L’implémentation de l’UUID v7 dans n’importe quel langage est centrée sur « l’intégration de l’horodatage + la manipulation des bits de version/variante ».
En fonction de vos besoins, vous pouvez choisir entre utiliser une bibliothèque existante ou créer une implémentation minimale en interne.