Maison > Article > développement back-end > Analyse du mécanisme de verrouillage pessimiste implémenté par PHP et Redis
Cet article présente principalement le mécanisme de verrouillage pessimiste implémenté par PHP+redis, présente brièvement le mécanisme de verrouillage redis, le verrouillage optimiste, le verrouillage pessimiste et d'autres concepts, et analyse les techniques d'exploitation associées du verrouillage pessimiste implémentées par php+redis sous la forme d'exemples. Il en faut. Les amis peuvent se référer à
Cet article décrit le verrou pessimiste implémenté par PHP+redis à titre d'exemple. Partagez-le avec tout le monde pour votre référence, les détails sont les suivants :
Mécanisme de verrouillage
Les verrous couramment utilisés sont divisés en verrous optimistes et verrous pessimistes. , une brève introduction à ces deux types de verrous est fournie comme connaissance de base de cet article. Les étudiants qui ont déjà une connaissance suffisante de ce type de connaissances peuvent sauter cette partie.
Verrouillage optimiste
Regardons d'abord l'explication sur l'encyclopédie Baidu : la plupart d'entre eux sont basés sur la version des données ( Version ) mécanisme d'enregistrement . Qu'est-ce qu'une version de données ? Il s'agit d'ajouter un identifiant de version aux données. Dans les solutions de version basées sur des tables de base de données, cela est généralement réalisé en ajoutant un champ « version » à la table de base de données. Lorsque les données sont lues, ce numéro de version est également lu, et lors d'une mise à jour ultérieure, ce numéro de version est incrémenté de un. À ce stade, les données de version des données soumises sont comparées aux informations de version actuelle de l'enregistrement correspondant dans la table de base de données. Si le numéro de version des données soumises est supérieur au numéro de version actuel de la table de base de données, il sera. mises à jour, sinon elles seront considérées comme des données expirées.
En fait, pour parler franchement, c'est comme s'il n'y avait qu'un seul tapis roulant dans une salle de sport, et qu'il y avait une machine à numéroter à l'entrée de la salle de sport. Tous ceux qui entrent dans la salle de sport doivent obtenir un numéro au préalable. ils peuvent entrer. Si vous courez. S'il y a quelqu'un sur le tapis roulant, réchauffez-vous et buvez de l'eau. S'il n'y a personne sur le tapis roulant, vérifiez si le numéro actuellement affiché sur le tapis roulant (le numéro de la dernière personne qui a utilisé le tapis roulant). tapis roulant) est plus petit que celui que vous tenez. S'il est plus petit, peut être utilisé autrement, cela signifie que le numéro a été dépassé. En réalité, nous savons tous que nous devons soit partir, soit réorganiser, mais nous ne pouvons pas sauter. dans la file d'attente. La même chose est vraie dans le système et une erreur est généralement renvoyée.
Verrouillage pessimiste
De même, jetons un coup d'œil à l'explication de l'Encyclopédie Baidu : il a de fortes caractéristiques exclusives et exclusives. Cela fait référence à une attitude conservatrice à l'égard des données modifiées par le monde extérieur (y compris d'autres transactions courantes du système et le traitement des transactions provenant de systèmes externes). Par conséquent, les données sont conservées dans un état verrouillé pendant tout le processus de traitement des données. La mise en œuvre du verrouillage pessimiste repose souvent sur le mécanisme de verrouillage fourni par la base de données (seul le mécanisme de verrouillage fourni par la couche base de données peut véritablement garantir l'exclusivité de l'accès aux données. Sinon, même si le mécanisme de verrouillage est implémenté dans ce système, il n'y a pas garantir que le système externe ne modifiera pas les données).
Ensuite, dans la même explication populaire, c'est la salle de sport. Cette fois, il n'y a pas besoin de file d'attente à la porte, mais une clé (une seule) est accrochée. Quiconque veut entrer doit se procurer cette clé. Ceux qui obtiennent la clé peuvent entrer, que ce soit pour se réchauffer ou boire de l'eau. Vous pouvez toujours courir, jusqu'à ce qu'il sorte et accroche la clé au mur, vous pouvez vous battre pour la suivante, et ce n'est qu'après l'avoir obtenue que vous pourrez rentrer. Cela semble un peu inhumain, donc Le verrouillage pessimiste est plus adapté aux scénarios de forte cohérence, mais l'efficacité est relativement faible, en particulier la concurrence de lecture est faible. Le verrouillage optimiste convient aux scénarios avec plus de lectures, moins d'écritures et moins de conflits de concurrence.
Contexte
Permettez-moi d'abord de parler du contexte de développement de cet article, afin que tout le monde puisse comprendre pourquoi pessimiste le verrouillage est utilisé et ce qu'il y a dans l'article Conception détaillée de la serrure.
Système de distribution des tâches : il existe un grand nombre de tâches (articles) dans le pool de tâches (mysql), qui nécessitent désormais l'assistance de l'utilisateur pour l'édition. La configuration système requise de base est la suivante (version simplifiée) :
1. Poussez les utilisateurs intéressés par les tâches de la catégorie vers l'éditeur d'utilisateurs ;2. Une fois que l'utilisateur a modifié et soumis une tâche, la tâche suivante sera automatiquement poussée ; est attribué à l'utilisateur à la fois ;
4. Si un Si l'utilisateur occupe une tâche pendant plus d'une certaine période de temps, la tâche sera automatiquement libérée et la tâche sera entrée dans le pool de tâches et recirculée. ;
Il y a deux objectifs :
1. Une tâche ne peut être détenue que par un seul utilisateur à la fois
2 Éviter les tâches mortes, c'est-à-dire éviter que les tâches soient suspendues. par les utilisateurs Possédé depuis longtemps et ne peut être libéré. Idées
En raison de la grande quantité de concurrence du système et des opérations d'écriture fréquentes, le choix du verrouillage pessimiste pour contrôler chaque tâche ne peut être reçu que par une seule utilisateur en même temps. Les idées principales sont les suivantes :
1. Trouvez des tâches attribuables dans le pool de tâches
2. Sélectionnez une tâche selon un certain ordre en tant que tâche push candidate ; comparez les candidats Poussez la tâche à verrouiller ;4. Si le verrouillage est réussi, transférez la tâche à l'utilisateur et modifiez le statut de la tâche et le statut de l'utilisateur correspondants 5. a été réclamé, répétez 2 à 5, jusqu'à ce que la poussée réussisse.
RéaliserIci, nous introduisons uniquement le mécanisme d'implémentation du verrouillage, et le reste de la logique métier est ignoré. Étant donné que le processus de verrouillage ne doit pas être démonté, ce qui est souvent appelé opération atomique, l'opération setnx dans redis est choisie comme méthode de verrouillage.
La version simplifiée du code est la suivante :
function lock($strMutex, $intTimeout) { $objRedis = new Redis(); //使用setnx原子型操作加锁 $intRet = $objRedis->setnx($strMutex, 1); if ($intRet) { //设置过期时间,防止死任务的出现 $objRedis->expire($strMutex, $intTimeout); return true; } return false; }
Il y a un problème avec ce code, c'est-à-dire que setnx réussit , mais l'expiration échoue. Il se peut qu'il y ait des tâches mortes. Une manière courante de résoudre ce problème consiste à utiliser la méthode incr au lieu de setnx, comme suit :
function lock($strMutex, $intTimeout, $intMaxTimes = 0) { $objRedis = new Redis(); //使用incr原子型操作加锁 $intRet = $objRedis->incr($strMutex); if ($intRet === 1) { //设置过期时间,防止死任务的出现 $objRedis->expire($strMutex, $intTimeout); return true; } if ($intMaxTimes > 0 && $intRet >= $intMaxTimes && $objRedis->ttl($strMutex) === -1) { //当设置了最大加锁次数时,如果尝试加锁次数大于最大加锁次数并且无过期时间则强制解锁 $objRedis->del($strMutex); } return false; }
Ce code passe $intMaxTimesPour garantir que même en cas d'expiration, le déverrouillage peut être forcé, garantissant ainsi qu'il n'y aura pas de tâches mortes dans le système.
Y a-t-il une meilleure façon ?
En fait, l'opération set dans redis est compatible avec setnx et prend en charge la définition du délai d'expiration.
function lock($strMutex, $intTimeout) { $objRedis = new Redis(); //使用setnx操作加锁,同时设置过期时间 $strRet = $objRedis->set($strMutex, 1, 'ex', $intTimeout, 'nx'); if ($strRet === 'OK') { return true; } return false; }
Je pense que cette méthode est la meilleure à l'heure actuelle, mais pourquoi n'avez-vous pas introduit cette méthode directement au lieu d'introduire d'abord la méthode incr ? En fait, les étudiants attentifs peuvent voir qu'il y a deux mots gras « général » dans l'aspect ci-dessus. La raison pour laquelle je dis cela est que la méthode set ne prend en charge que plusieurs paramètres de la version redis2.6.12.
Le niveau est limité, les corrections sont les bienvenues~
Ce qui précède est l'intégralité du contenu de cet article. J'espère qu'il sera utile à l'apprentissage de chacun. Pour plus de contenu connexe, veuillez faire attention. le site PHP chinois !
Recommandations associées :
Résumé de l'utilisation des fonctions variables en php
Méthode non récursive d'implémentation des arborescences PHP
Comment utiliser PHP pour obtenir la véritable adresse IP du client utilisateur
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!