Contexte professionnel : des verrous sont nécessaires dans les jeux d'échecs et de cartes en salle pour empêcher une lecture sale des données Redis causée par des opérations simultanées, par exemple l'ajout de l'action d'un utilisateur entrant dans une salle :
En cas de concurrence, get RoomUsers aura des lectures sales
Solution : verrouiller la salle pour permettre à un seul client d'opérer dans une salle à la fois ; time et autres clients simultanés Attendez ; c'est-à-dire ----- blocage du verrouillage ;
Verrouillage : Il existe plusieurs méthodes de verrouillage Redis : incr, set, setnx, hSetnx, vous pouvez vous référer à cet article : Comment lock redis Une sorte d'implémentation
Recommandé :Tutoriel vidéo PHP
Ici, j'utilise set this way
$roomId = $_GET['roomId']; $user = $_GET['user']; // '张三' $key = "LockRoom:{$roomId}"; $value = $roomId.uniqid(); $ex = 3; // 如果 $key 不存在的话,就设置 $key 的值为 $value,且有效期为 3s; // return TRUE / FALSE while(true){ $res = $this->redis->set($key, $value, ['nx', 'ex' => $ex]); if($res) { break; } usleep(5000); } // 将用户添加进房间 $roomUsers = $this->redis->get("Room:{$roomId}:Users"); // ['李四', '王五'] $roomUsers[] = $user; $this->redis->set("Room:{$roomId}:Users", $roomUsers); // ['李四', '王五', '张三']
Déverrouillage : bien sûr, vous devez déverrouiller après l'opération, non Pour déverrouiller, il faut attendre au moins 3 secondes ;
Pour déverrouiller, utilisez delete pour supprimer la clé mais il y a un écueil ici Vous ne pouvez pas utiliser delete directement car c'est supposé. que le client01 obtient le verrou et que le temps dépasse 3 secondes pendant le processus d'ajout d'un utilisateur à la salle, à ce moment-là, le client02 obtiendra également le verrou et définira 3S, puis lorsque le client01 terminera l'opération et supprimera la clé, le verrou sera défini. par client02 sera supprimé
Il est recommandé d'utiliser le code Lua pour effectuer la suppression, car l'exécution de Lua est du sexe atomique.
// 将用户添加进房间 $roomUsers = $this->redis->get("Room:{$roomId}:Users"); // ['李四', '王五'] $roomUsers[] = $user; $this->redis->set("Room:{$roomId}:Users", $roomUsers); // ['李四', '王五', '张三'] // lua 脚本解锁 // 先判断 key的值是否为 value, TRUE 才会删除, 所以 $value 的设计要有随机唯一性 $script = 'if redis.call("get",KEYS[1]) == ARGV[1] then return redis.call("del",KEYS[1]) else return 0 end '; $this->redis->eval($script, array($key , $value), 1);
Pour plus de connaissances connexes, veuillez prêter attention à la colonne tutoriel d'introduction à Redis
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!