Maison > base de données > Redis > le corps du texte

PHP+redis implémente les opérations de verrouillage et de déverrouillage

Libérer: 2020-06-20 16:55:06
avant
3964 Les gens l'ont consulté

PHP+redis implémente les opérations de verrouillage et de déverrouillage

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 :

PHP+redis implémente les opérations de verrouillage et de déverrouillage

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); // ['李四', '王五', '张三']
Copier après la connexion

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);
Copier après la connexion

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!

Étiquettes associées:
source:segmentfault.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