欧美亚洲中文,在线国自产视频,欧洲一区在线观看视频,亚洲综合中文字幕在线观看

      1. <dfn id="rfwes"></dfn>
          <object id="rfwes"></object>
        1. 站長資訊網(wǎng)
          最全最豐富的資訊網(wǎng)站

          php+redis實現(xiàn)加鎖與解鎖操作

          php+redis實現(xiàn)加鎖與解鎖操作

          業(yè)務背景:在房間棋牌游戲中需要用到鎖來防止并發(fā)操作引起的 redis 數(shù)據(jù)臟讀問題;例如添加用戶進入房間的動作:

          php+redis實現(xiàn)加鎖與解鎖操作

          并發(fā)的情況下,get RoomUsers 會有臟讀現(xiàn)象;

          解決思路:加鎖房間來實現(xiàn) 一個房間每次只允許一個客戶端操作,其他并發(fā)客戶端則等待;也就是—–堵塞鎖;

          加鎖:redis加鎖方式有幾種: incr、set、setnx、hSetnx,可以參考這篇文章:redis加鎖的幾種實現(xiàn)

          推薦:PHP視頻教程

          這里我用到 set 這種方式

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

          解鎖:操作完當然要解鎖了,不解鎖起碼要等待 3秒;

          解鎖用 delete 刪除 key; 但是這里有個坑,不能直接用 delete,因為假設 client01 獲得了鎖,在添加用戶進入房間的過程中 時間超過了 3秒 ,這個時候client02 就會同樣獲得鎖并且設置3S,然后當client01 操作完之后 delete key , 就把 client02 設置的鎖刪除了;

          這里推薦用 lua 代碼執(zhí)行刪除,因為lua 執(zhí)行具有原子性。

          // 將用戶添加進房間 $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);

          贊(0)
          分享到: 更多 (0)
          網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號