Si vous êtes familier avec les commandes Redis, vous pouvez immédiatement penser à utiliser l'opération set if not exist de Redis pour l'implémenter, et la méthode d'implémentation standard actuelle est le SET nom_ressource my_random_value NX PX 30000 séries de commandes, où :
resource_name signifie la ressource à verrouiller
NX signifie la définir si elle n'existe pas
PX 30000 signifie que le délai d'expiration est de 30000 millisecondes, soit 30 secondes
my_random_value Cette valeur est utilisée par tous les clients. La fin doit être unique, et tous les acquéreurs (concurrents) d'une même clé ne peuvent pas avoir la même valeur.
La valeur de value doit être un nombre aléatoire principalement pour déverrouiller le verrou de manière plus sûre, utilisez un script pour indiquer à Redis : Uniquement lorsque la clé existe et que la valeur stockée est la même que la valeur que j'ai spécifiée. puis-je être informé que la suppression a réussi. Ceci peut être réalisé grâce au script Lua suivant :
1 2 3 4 5 |
|
Par exemple : le client A obtient un verrou de ressource, mais est immédiatement bloqué par une autre opération. Lorsque le client A souhaite libérer le verrou après avoir exécuté d'autres opérations, le verrou d'origine a déjà été chronométré. out. Et il a été automatiquement libéré par Redis, et pendant cette période, le verrouillage des ressources a été à nouveau acquis par le client B.
Le script Lua est utilisé car le jugement et la suppression sont deux opérations, il est donc possible que A libère automatiquement le verrou après son expiration dès qu'il a jugé, puis B a acquis le verrou, puis A appelle Del, provoquant le déverrouillage de B.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
|
Regardons d'abord la fonction lottery() Ici, lors de la saisie de la fonction, utilisez d'abord SET resource_name my_random_value NX PX 30000 pour verrouiller. valeur. Si l'opération échoue, retournez directement et laissez l'utilisateur réessayer. Si la logique de déverrouillage est exécutée avec succès en différé, la logique de déverrouillage consiste à exécuter le script Lua mentionné ci-dessus, puis à effectuer le traitement métier.
Nous avons exécuté deux goroutines dans la fonction main() pour appeler simultanément la fonction lottery(). L'une des opérations échouera directement car le verrou ne peut pas être obtenu.
Générer une valeur aléatoire
Utilisez SET nom_ressource my_random_value NX PX 30000 pour verrouiller
Si le verrouillage échoue, revenez directement
defer pour ajouter une logique de déverrouillage pour vous en assurer sera débloqué lorsque la fonction se termine, Exécuter
Exécuter la logique métier
Dans le cas d'une seule instance, si cette instance se bloque, toutes les requêtes échoueront car le verrou ne peut pas être obtenu, nous avons donc besoin de plusieurs Instances Redis distribuées dans différents L'instance Redis sur la machine et le verrouillage de la plupart des nœuds peuvent être verrouillés avec succès. Il s'agit de l'algorithme RedLock. Nous devons acquérir des verrous sur plusieurs instances Redis en même temps, mais cela est en fait basé sur un algorithme à instance unique.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
|
Dans le code ci-dessus, nous utilisons la multi-base de données de Redis pour simuler plusieurs instances maîtres Redis. Généralement, nous choisirons 5 instances Redis. Dans l'environnement réel, ces instances doivent être distribuées sur différentes machines. échecs simultanés.
Dans la logique de verrouillage, nous exécutons principalement SET resource_name my_random_value NX PX 30000 sur chaque instance Redis pour obtenir le verrou, puis plaçons le client qui a réussi à obtenir le verrou dans un canal (il peut y avoir des problèmes de concurrence lors de l'utilisation de slice ici), et utilisez sync.WaitGroup attend la fin de l’opération d’acquisition du verrou.
Ensuite, ajoutez un délai pour libérer la logique de verrouillage. La logique de déverrouillage est très simple, il suffit de libérer le verrou obtenu avec succès.
Enfin, jugez si le nombre de verrous acquis avec succès est supérieur à la moitié. Si plus de la moitié des verrous ne sont pas acquis, cela signifie que le verrouillage a échoué.
Si le verrouillage réussit, l'étape suivante consiste à effectuer le traitement commercial.
Générer une valeur aléatoire
et l'envoyer à chaque instance Redis pour utilisationSET resource_name my_random_value NX PX 30000
Lock
Attendez que toutes les opérations d'acquisition de verrou soient terminées
defer ajoute une logique de déverrouillage pour garantir que il sera déverrouillé à la sortie de la fonction Exécution, ici différer d'abord puis juger car il est possible d'obtenir le verrou d'une partie de l'instance Redis, mais comme il ne dépasse pas la moitié, il sera quand même jugé comme un échec de verrouillage
Déterminez si le verrouillage de plus de la moitié de l'instance Redis a été obtenu, s'il n'y a pas d'explication. Si le verrouillage échoue, revenez directement à
pour exécuter la logique métier
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!