Maison  >  Article  >  développement back-end  >  Manière correcte de déverrouiller le verrouillage Redis

Manière correcte de déverrouiller le verrouillage Redis

小云云
小云云original
2017-12-14 13:35:582755parcourir

Redis est un bon ami de PHP. Lors de l'écriture d'affaires en PHP, le concept de verrouillage est parfois utilisé. Une seule personne peut opérer un certain comportement en même temps. À ce stade, nous devons utiliser des verrous. Il existe plusieurs méthodes de verrouillage. PHP ne peut pas utiliser de verrous en mémoire, ni utiliser ZooKeeper pour verrouiller. À l'heure actuelle, nous choisissons généralement Redis comme mécanisme de verrouillage. Cet article partage principalement avec vous la bonne méthode pour déverrouiller Redis, dans l'espoir d'aider tout le monde.

setnx

La structure de données la plus simple verrouillée dans Redis est la chaîne. Dans les premiers jours, setnx était généralement utilisé pour les opérations de verrouillage. Cette commande consiste à définir un val lorsque :lock n'existe pas. Vous vous souviendrez peut-être également d'utiliser expire pour augmenter l'expiration du verrou. Pour déverrouiller l'opération, utilisez le. del commande. Le pseudo code est le suivant :

if (Redis::setnx("my:lock", 1)) {
  Redis::expire("my:lock", 10);
  // ... do something

  Redis::del("my:lock")
}

Il y a en fait un problème ici. Le problème est que s'il y a un crash ou un autre comportement. entre setnx et expire, le verrou ne peut pas être libéré. Une autre solution d'optimisation peut donc consister à stocker l'horodatage dans le verrou. Déterminez la longueur de l’horodatage.

set

Maintenant, il est officiellement recommandé d'utiliser set directement pour implémenter le verrou. Nous pouvons utiliser la commande set pour remplacer setnx, qui ressemble à ce qui suit

if (Redis::set("my:lock", 1, "nx", "ex", 10)) {
  ... do something

  Redis::del("my:lock")
}

Le code ci-dessus définit my:lock sur 1 si et seulement si ceci Lorsque le verrou n'existe pas, le délai d'expiration est fixé à 10 une fois le réglage terminé.

Le mécanisme d'acquisition des verrous est correct, mais le mécanisme de suppression des verrous en utilisant directement del est incorrect. Parce que cela peut conduire à la suppression accidentelle des verrous d'autres personnes.

Par exemple, j'ai verrouillé ce verrou pendant 10 secondes, mais le temps de traitement était supérieur à 10 secondes. Au bout de 10 secondes, le verrou a automatiquement expiré, a été retiré par d'autres et a été reverrouillé. Puis à ce moment-là, lorsque j'appelle à nouveau Redis::del, il supprimera le verrou créé par d'autres.

Le responsable a également des suggestions pour déverrouiller les commandes. Il est recommandé d'utiliser le script lua, d'effectuer d'abord get, puis d'exécuter del

Le programme devient :

$token = rand(1, 100000);

function lock() {
  return Redis::set("my:lock", $token, "nx", "ex", 10);
}

function unlock() {
  $script = `
if redis.call("get",KEYS[1]) == ARGV[1]
then
  return redis.call("del",KEYS[1])
else
  return 0
end  
  `
  return Redis::eval($script, "my:lock", $token)
}

if (lock()) {
  // do something

  unlock();
}

Le jeton ici est un nombre aléatoire Lors du verrouillage, ce jeton est stocké dans my:lock dans redis. Lors du déverrouillage, récupérez d'abord le jeton dans le verrou. it, Les jetons sont cohérents, ce qui signifie que le verrou a été défini par moi auparavant, sinon cela signifie que le verrou a expiré et a été défini par quelqu'un d'autre, et je ne devrais effectuer aucune opération dessus.

Donc : n'utilisez plus setnx, utilisez set directement pour l'implémentation du verrouillage.

Recommandations associées :

php Utiliser le verrouillage Redis pour limiter la classe d'accès simultané

php Exemple d'utilisation du verrouillage Redis pour limiter la classe d'accès simultané

Résumé des méthodes courantes d'exploitation de Redis en PHP

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:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn