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 !
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); }
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();
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); }
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); } }
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!