Que sont les UUID et pourquoi sont-ils utiles ?  – Informatique CloudSavvy
Agence web » Actualités du digital » Que sont les UUID et pourquoi sont-ils utiles ? – Informatique CloudSavvy

Que sont les UUID et pourquoi sont-ils utiles ? – Informatique CloudSavvy

Un identifiant universel unique (UUID) est une forme spécifique d’identifiant qui peut être considérée comme unique en toute sécurité pour la plupart des objectifs pratiques. Deux UUID correctement générés ont une chance pratiquement négligeable d’être identiques, même s’ils sont créés dans deux environnements différents par des parties distinctes. C’est pourquoi on dit que les UUID sont universellement unique.

Dans cet article, nous examinerons les caractéristiques des UUID, le fonctionnement de leur unicité et les scénarios dans lesquels ils peuvent simplifier l’identification des ressources. Bien que nous abordions les UUID du point de vue commun des logiciels qui interagissent avec les enregistrements de la base de données, ils sont largement applicables à tout cas d’utilisation où la génération décentralisée d’un identifiant unique est requise.

Qu’est-ce qu’un UUID ?

Un UUID est simplement une valeur que vous pouvez traiter en toute sécurité comme unique. Le risque de collision est si faible que vous pouvez raisonnablement choisir de l’ignorer complètement. Vous pouvez voir des UUID référencés en utilisant des termes différents (GUID, ou Globally Unique Identifier, est la sémantique préférée de Microsoft), mais la signification et l’effet restent les mêmes.

Un vrai UUID est un identifiant unique qui est généré et représenté par un format standardisé. Les UUID valides sont définis par la RFC 4122 ; cette spécification décrit les algorithmes qui peuvent être utilisés pour générer des UUID qui préservent l’unicité entre les implémentations, sans autorité centrale émettrice.

La RFC comprend cinq algorithmes différents qui utilisent chacun un mécanisme différent pour produire une valeur. Voici un bref résumé des « versions » disponibles :

  • Version 1 – Basée sur le temps – Combine un horodatage, une séquence d’horloge et une valeur spécifique au périphérique générateur (généralement son adresse MAC) pour produire une sortie unique pour cet hôte à ce moment précis.
  • Version 2 – Sécurité DCE – Cette version a été développée comme une évolution de la version 1 pour une utilisation avec Distributed Computing Environment (DCE). Il n’est pas largement utilisé.
  • Version 3 – Basée sur le nom (MD5) – MD5 hache un « espace de noms » et un « nom » pour créer une valeur unique pour ce nom dans l’espace de noms. La génération d’un autre UUID avec le même espace de noms et le même nom produira une sortie identique, de sorte que cette méthode fournit des résultats reproductibles.
  • Version 4 – Aléatoire – La plupart des systèmes modernes ont tendance à opter pour UUID v4 car il utilise la source de nombres aléatoires ou pseudo-aléatoires de l’hôte pour émettre ses valeurs. Les chances que le même UUID soit produit deux fois sont pratiquement négligeables.
  • Version 5 – Basée sur le nom (SHA-1) – Ceci est similaire à la version 3 mais il utilise l’algorithme SHA-1 plus fort pour hacher l’espace de noms et le nom d’entrée.

Bien que la RFC fasse référence aux algorithmes en tant que versions, cela ne signifie pas que vous devez toujours utiliser la version 5 car elle est apparemment la plus récente. Celui à choisir dépend de votre cas d’utilisation ; dans de nombreux scénarios, la v4 est choisie en raison de sa nature aléatoire. Cela en fait le candidat idéal pour les scénarios simples « donnez-moi un nouvel identifiant ».

Les algorithmes de génération émettent un entier non signé de 128 bits. Cependant, les UUID sont plus souvent considérés comme des chaînes hexadécimales et peuvent également être stockés sous la forme d’une séquence binaire de 16 caractères. Voici un exemple de chaîne UUID :

16763be4-6022-406e-a950-fcd5018633ca

La valeur est représentée par cinq groupes de caractères alphanumériques séparés par des tirets. Les tirets ne sont pas un composant obligatoire de la chaîne ; leur présence est due aux détails historiques de la spécification UUID. Ils rendent également l’identifiant beaucoup plus facile à percevoir pour les yeux humains.

Cas d’utilisation UUID

Le principal cas d’utilisation des UUID est la génération décentralisée d’identifiants uniques. Vous pouvez générer l’UUID n’importe où et le considérer en toute sécurité comme unique, qu’il provienne de votre code backend, d’un appareil client ou de votre moteur de base de données.

Les UUID simplifient la détermination et la maintenance de l’identité des objets dans des environnements déconnectés. Historiquement, la plupart des applications utilisaient un champ entier auto-incrémenté comme clé primaire. Lorsque vous créez un nouvel objet, vous ne pouvez pas connaître son ID tant que après il avait été inséré dans la base de données. Les UUID vous permettent de déterminer l’identité beaucoup plus tôt dans votre application.

Voici une démo PHP de base qui démontre la différence. Regardons d’abord le système basé sur les nombres entiers :

class BlogPost {
    public function __construct(
        public readonly ?int $Id,
        public readonly string $Headline,
        public readonly ?AuthorCollection $Authors=null) {}
}
 
#[POST("/posts")]
function createBlogPost(HttpRequest $Request) : void {
    $headline = $Request -> getField("Headline");
    $blogPost = new BlogPost(null, $headline);
}

Nous devons initialiser le $Id propriété avec null parce que nous ne pouvons pas savoir qu’il s’agit d’une pièce d’identité réelle tant que après il a été conservé dans la base de données. Ce n’est pas idéal – $Id ne devrait pas vraiment être nullable et cela permet BlogPost instances à exister dans un état incomplet.

Le passage aux UUID résout le problème :

class BlogPost {
    public function __construct(
        public readonly string $Uuid,
        public readonly string $Headline,
        public readonly ?AuthorCollection $Authors=null) {}
}
 
#[POST("/posts")]
function createBlogPost(HttpRequest $Request) : void {
    $headline = $Request -> getField("Headline");
    $blogPost = new BlogPost("16763be4-...", $headline);
}

Les identifiants de publication peuvent désormais être générés dans l’application sans risquer de doubler les valeurs. Cela garantit que les instances d’objet représentent toujours un état valide et n’ont pas besoin de propriétés d’ID nullables maladroites. Le modèle facilite également la gestion de la logique transactionnelle ; les enregistrements enfants qui ont besoin d’une référence à leur parent (comme notre message Author associations) peuvent être insérées immédiatement, sans aller-retour dans la base de données pour récupérer l’ID attribué au parent.

À l’avenir, votre application de blog pourrait déplacer plus de logique dans le client. Peut-être que le frontend prend en charge la création complète de brouillons hors ligne, créant ainsi BlogPost instances qui sont temporairement conservées sur l’appareil de l’utilisateur. Désormais, le client peut générer l’UUID de la publication et le transmettre au serveur lorsque la connectivité réseau est rétablie. Si le client récupérait par la suite la copie du brouillon du serveur, il pourrait la faire correspondre à tout état local restant car l’UUID serait déjà connu.

Les UUID vous aident également à combiner des données provenant de diverses sources. La fusion de tables de base de données et de caches utilisant des clés entières peut être fastidieuse et source d’erreurs. Les UUID offrent un caractère unique non seulement au sein des tables, mais au niveau de l’univers entier. Cela en fait de bien meilleurs candidats pour les structures répliquées et les données fréquemment déplacées entre différents systèmes de stockage.

Mises en garde lorsque les UUID rencontrent des bases de données

Les avantages des UUID sont assez convaincants. Cependant, il y a plusieurs pièges à surveiller lors de leur utilisation dans des systèmes réels. Un facteur important en faveur des identifiants entiers est qu’ils sont faciles à mettre à l’échelle et à optimiser. Les moteurs de base de données peuvent facilement indexer, trier et filtrer une liste de nombres qui ne va que dans une seule direction.

On ne peut pas en dire autant des UUID. Pour commencer, les UUID sont quatre fois plus gros que les entiers (36 octets contre 4 octets) ; pour les grands ensembles de données, cela pourrait être une considération importante en soi. Les valeurs sont également beaucoup plus délicates à trier et à indexer, en particulier dans le cas des UUID aléatoires les plus courants. Leur nature aléatoire signifie qu’ils n’ont pas d’ordre naturel. Cela nuira aux performances d’indexation si vous utilisez un UUID comme clé primaire.

Ces problèmes peuvent s’aggraver dans une base de données bien normalisée qui fait un usage intensif de clés étrangères. Maintenant, vous pouvez avoir de nombreuses tables relationnelles, chacune contenant des références à vos UUID de 36 octets. Finalement, la mémoire supplémentaire nécessaire pour effectuer des jointures et des tris pourrait avoir un impact significatif sur les performances de votre système.

Vous pouvez partiellement atténuer les problèmes en stockant vos UUID sous forme de données binaires. Cela signifie un BINARY(16) colonne au lieu de VARCHAR(36). Certaines bases de données telles que PostgreSQL incluent un UUID Type de données; d’autres comme MySQL ont des fonctions qui peuvent convertir une chaîne UUID en sa représentation binaire, et vice versa. Cette approche est plus efficace, mais n’oubliez pas que vous utiliserez toujours des ressources supplémentaires pour stocker et sélectionner vos données.

Une stratégie efficace peut consister à conserver des entiers comme clés primaires, mais à ajouter un champ UUID supplémentaire pour la référence de votre application. Les tables de liens relationnels peuvent utiliser des ID pour améliorer les performances pendant que votre code récupère et insère des objets de niveau supérieur avec des UUID. Tout dépend de votre système, de son échelle et de vos priorités : lorsque vous avez besoin d’une génération d’ID décentralisée et de fusions de données simples, les UUID sont la meilleure option, mais vous devez reconnaître les compromis.

Résumé

Les UUID sont des valeurs uniques que vous pouvez utiliser en toute sécurité pour la génération d’identité décentralisée. Collisions sont possible mais devraient être si rares qu’ils peuvent être écartés. Si vous génériez un milliard d’UUID par seconde pendant un siècle entier, la probabilité de rencontrer un doublon serait d’environ 50 % en supposant qu’une entropie suffisante était disponible.

Vous pouvez utiliser des UUID pour établir une identité indépendamment de votre base de données, avant qu’une insertion ne se produise. Cela simplifie le code au niveau de l’application et empêche les objets mal identifiés d’exister dans votre système. Les UUID facilitent également la réplication des données en garantissant l’unicité quel que soit le magasin de données, l’appareil ou l’environnement, contrairement aux clés entières traditionnelles qui fonctionnent au niveau de la table.

Bien que les UUID soient désormais omniprésents dans le développement de logiciels, ils ne constituent pas une solution parfaite. Les nouveaux arrivants ont tendance à se fixer sur la possibilité de collisions, mais cela ne devrait pas être votre principale préoccupation, à moins que votre système ne soit si sensible que l’unicité doit être garantie.

Le défi le plus apparent pour la plupart des développeurs concerne le stockage et la récupération des UUID générés. Utiliser naïvement un VARCHAR(36) (ou en supprimant les traits d’union et en utilisant VARCHAR(32)) pourrait paralyser votre application au fil du temps car la plupart des optimisations d’indexation de base de données seront inefficaces. Recherchez les capacités de gestion UUID intégrées de votre système de base de données pour vous assurer d’obtenir les meilleures performances possibles de votre solution.

★★★★★