Maison  >  Article  >  base de données  >  PHP+redis implémente les opérations de verrouillage et de déverrouillage

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

尚
avant
2020-06-20 16:55:063960parcourir

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); // ['李四', '王五', '张三']

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!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer