Maison > base de données > Redis > Vous apprendre à utiliser correctement SETNX de Redis pour implémenter le mécanisme de verrouillage

Vous apprendre à utiliser correctement SETNX de Redis pour implémenter le mécanisme de verrouillage

藏色散人
Libérer: 2020-10-28 16:56:30
avant
3507 Les gens l'ont consulté

La colonne suivante du Tutoriel Redis vous présentera l'utilisation correcte du SETNX de Redis pour implémenter le mécanisme de verrouillage, j'espère que ce sera le cas. utile aux amis dans le besoin !

Vous apprendre à utiliser correctement SETNX de Redis pour implémenter le mécanisme de verrouillage

setNX est l'abréviation de set s'il n'existe pas, c'est-à-dire qu'il est défini uniquement lorsqu'il n'existe pas. Il renvoie 1 lorsque le réglage est réussi et 0 lorsque le réglage est réussi. le réglage échoue. Il peut être utilisé pour obtenir l'effet de verrouillage, mais de nombreuses personnes rencontrent des problèmes dont elles ne tiennent pas compte lors de l'utilisation.

Par exemple, une certaine interface pour interroger une base de données ajoute un cache en raison d'un grand nombre de requêtes et le configure pour qu'il s'actualise après l'expiration du cache. Lorsque le degré de concurrence est relativement important et que le cache expire, un grand nombre de requêtes simultanées interrogeront directement la base de données, provoquant une avalanche. Le problème d'avalanche peut être évité si un mécanisme de verrouillage est utilisé pour contrôler une seule demande de mise à jour du cache. Voici la méthode de verrouillage à laquelle beaucoup de gens pensent inconsciemment

$rs = $redis->setNX($key, $value);
if ($rs) {
    //处理更新缓存逻辑
    // ......
    //删除锁
    $redis->del($key);
}
Copier après la connexion

Obtenez le verrou via setNX En cas de succès, mettez à jour le cache, puis supprimez le verrou. En fait, il y a ici un sérieux problème : si le cache se ferme de manière inattendue pour une raison quelconque, le verrou ne sera pas supprimé et existera toujours, de sorte que le cache ne sera jamais mis à jour. Afin de résoudre ce problème, certaines personnes peuvent penser à définir un délai d'expiration pour le verrou, comme suit

$redis->multi();
$redis->setNX($key, $value);
$redis->expire($key, $ttl);
$redis->exec();
Copier après la connexion

Parce que setNX n'a ​​pas pour fonction de définir le délai d'expiration, il doit utiliser Expire pour le définir , et Multi/Exec doit être utilisé pour garantir l'atomicité demandée afin d'empêcher setNX de réussir mais d'échouer à expirer. Il y a toujours un problème avec cela : lorsque plusieurs requêtes arrivent, même si une seule requête setNX peut réussir, l'expiration de n'importe quelle requête peut réussir. Cela signifie que même si le verrou ne peut pas être obtenu, le délai d'expiration peut être actualisé, ce qui fait que le verrou reste. verrouillé. C'est efficace, mais cela ne résout toujours pas le problème ci-dessus. De toute évidence, setNX ne peut pas répondre à la demande. À partir de Redis 2.6.12, SET couvre les fonctions de SETEX. SET lui-même inclut également la fonction de réglage du délai d'expiration, donc l'utilisation de SET peut résoudre les problèmes ci-dessus

$rs = $redis->set($key, $value, array('nx', 'ex' => $ttl));
if ($rs) {
    //处理更新缓存逻辑
    // ......
    //删除锁
    $redis->del($key);
}
Copier après la connexion

Cette étape. est en fait problématique. Si une requête prend plus de temps pour mettre à jour le cache que la période de validité du verrou, ce qui rend le verrou invalide pendant le processus de mise à jour du cache, une autre requête acquerra le verrou, mais la requête précédente le fera lorsque la mise à jour du cache sera terminée. terminé, si le verrou est supprimé directement, les verrous créés par d'autres demandes seront accidentellement supprimés. Donc pour éviter ce problème, vous pouvez introduire une valeur aléatoire lors de la création du verrou et la juger lors de la suppression du verrou

$rs = $redis->set($key, $random, array('nx', 'ex' => $ttl));
if ($rs) {
     //处理更新缓存逻辑
    // ......
    //先判断随机数,是同一个则删除锁
    if ($redis->get($key) == $random) {
        $redis->del($key);
    }
}
Copier après la connexion

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!

Étiquettes associées:
source:cnblogs.com
Déclaration de ce site Web
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
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal