Maison  >  Article  >  cadre php  >  Utilisation du générateur d'ID unique distribué par Laravel

Utilisation du générateur d'ID unique distribué par Laravel

Guanhui
Guanhuiavant
2020-06-17 17:20:545272parcourir

Utilisation du générateur d'ID unique distribué par Laravel

Dans les applications, un identifiant unique au monde est souvent requis comme clé primaire de base de données. Comment générer un identifiant unique au monde ?

Tout d'abord, vous devez déterminer si l'identifiant globalement unique est un entier ou une chaîne ? S'il s'agit d'une chaîne, l'UUID existant répond pleinement aux exigences et aucun travail supplémentaire n'est requis. L'inconvénient est que les chaînes occupent beaucoup d'espace en tant qu'identifiants et que l'efficacité de l'indexation est inférieure à celle des entiers.

Si un entier est utilisé comme ID, alors le type int 32 bits est d'abord exclu. Parce que la plage est trop petite, le type long 64 bits doit être utilisé.

Lorsque vous utilisez des nombres entiers comme identifiants, comment générer des identifiants auto-croissants, uniques au monde et non dupliqués ?

Option 1 : en utilisant l'ID auto-croissant de la base de données, à partir de 1, elle peut essentiellement obtenir une incrémentation continue. Oracle peut utiliser SEQUENCE et MySQL peut utiliser la clé primaire AUTO_INCREMENT Bien qu'il ne puisse pas garantir l'unicité globale, elle est unique pour chaque table et répond fondamentalement aux besoins.

L'inconvénient de l'ID auto-augmentant dans la base de données est que l'ID ne peut pas être obtenu avant que les données ne soient insérées. Une fois les données insérées, bien que l'identifiant obtenu soit unique, l'identifiant ne sera considéré comme valide qu'une fois la transaction soumise. Certaines données référencées de manière bidirectionnelle doivent être insérées puis mises à jour, ce qui est gênant.

La deuxième façon consiste à utiliser un générateur d'identifiant centralisé, qui peut être Redis ou ZooKeeper, ou vous pouvez utiliser une table de base de données pour enregistrer le dernier identifiant attribué.

Le plus gros inconvénient de cette méthode est qu'elle est trop complexe, nécessite une forte dépendance à l'égard de services tiers et que la configuration du code est lourde. De manière générale, plus la solution est complexe, moins elle est fiable et plus elle est pénible à tester.

La troisième méthode est similaire à l'algorithme Snowflake de Twitter, qui attribue un identifiant unique à chaque machine, puis implémente un identifiant globalement unique via horodatage + ID + incrémentation automatique. L'avantage de cette méthode est que l'algorithme de génération d'ID est complètement une machine sans état, n'a pas d'appels réseau et est efficace et fiable. L'inconvénient est que si des identifiants uniques sont répétés, des conflits d'identification se produiront.

L'algorithme Snowflake utilise un horodatage de 41 bits en millisecondes, plus un identifiant de machine de 10 bits et un numéro de série de 12 bits. En théorie, il peut prendre en charge jusqu'à 1 024 machines pour générer 4 096 000 numéros de série par seconde, ce qui est suffisant pour l'échelle de Twitter. .

Mais pour la plupart des applications ordinaires, il n'est pas nécessaire de dépasser 4 millions d'identifiants par seconde et le nombre de machines n'atteint pas 1024. Par conséquent, nous pouvons l'améliorer et utiliser une méthode de génération d'identifiants plus courte :

53bitID ​​​​se compose d'un horodatage de deuxième niveau de 32 bits + d'un incrément automatique de 16 bits + d'une identification de machine de 5 bits. Il accumule 32 machines et peut générer 65 000 numéros de série par seconde :

private static synchronized long nextId(long epochSecond) {
    if (epochSecond < lastEpoch) {
        // warning: clock is turn back:
        logger.warn("clock is back: " + epochSecond + " from previous:" + lastEpoch);
        epochSecond = lastEpoch;
    }
    if (lastEpoch != epochSecond) {
        lastEpoch = epochSecond;
        reset();
    }
    offset++;
    long next = offset & MAX_NEXT;
    if (next == 0) {
        logger.warn("maximum id reached in 1 second in epoch: " + epochSecond);
        return nextId(epochSecond + 1);
    }
    return generateId(epochSecond, next, SHARD_ID);}

L'horodatage est. soustrait d'une valeur fixe. Cette solution peut prendre en charge jusqu'à 2106.

Et si 65 000 numéros de série par seconde ne suffisaient pas ? Ce n'est pas grave, vous pouvez continuer à incrémenter l'horodatage et « emprunter » les 65 000 numéros de séquence pour la seconde suivante.

Dans le même temps, le problème du rappel de l'heure est également résolu.

L'identification de la machine utilise un schéma de nom d'hôte simple. Tant que le nom d'hôte correspond à host-1, host-2 peut extraire automatiquement l'identification de la machine sans configuration.

Enfin, pourquoi utiliser des entiers jusqu'à 53 bits au lieu d'entiers de 64 bits ? En effet, étant donné que la plupart des applications sont des applications Web, si vous souhaitez gérer JavaScript, l'entier maximum pris en charge par JavaScript est de 53 chiffres. Au-delà de ce nombre, JavaScript perdra en précision. Ainsi, un entier de 53 bits peut être lu directement par JavaScript, mais lorsqu'il dépasse 53 bits, il doit être converti en chaîne pour garantir un traitement correct par JavaScript, ce qui apportera une complexité supplémentaire à l'interface API. C'est également la raison pour laquelle l'interface API de Sina Weibo renvoie à la fois id et idstr.

Tutoriels recommandés : "PHP" "Tutoriel Laravel"

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer