<?php /** * * 實現分佈式鎖 * (1) 進程Asetnx,值爲超時的時間戳(t1),若是返回true,得到鎖。 * (2) 進程B用get 命令獲取t1,與當前時間戳比較,判斷是否超時,沒超時false,若是已超時執行步驟3 * (3) 計算新的超時時間t2,使用getset命令返回t3(這個值可能其餘線程已經修改過),若是t1==t3,得到鎖,若是t1!=t3說明鎖被其餘進程獲取了 * (4) 獲取鎖後,處理完業務邏輯,再去判斷鎖是否超時,若是沒超時刪除鎖,若是已超時,不用處理(防止刪除其餘進程的鎖) */ class Lock { protected $objRedis = null; public function __construct() { $this->setRedis(); } private function setRedis () { if (is_null($this->objRedis)) { $this->objRedis = new Redis(); $this->objRedis->connect("127.0.0.1", 6688); } } function getLock($lockname, $expiretime = 5) { $expireTime = time() + $expiretime; $getLock = $this->objRedis->setnx($lockname, $expireTime); if ($getLock == true) { //獲取鎖 return true; } //獲取鎖失敗 //判斷鎖超時 $t1 = $this->objRedis->get($lockname); if ($t1 > time()) { return false; } //鎖已經超時 $t2 = time() + $expiretime; $t3 = $this->objRedis->getset($lockname, $t2); if ($t1 == $t3) { return true; } //表明被別的進程獲取到鎖,須要把時間set回去 $this->objRedis->set($lockname, $t3); return false; } public function unlock($lockname) { $expireTime = $this->objRedis->get($lockname); if ($expireTime > time()) { $this->objRedis->del($lockname); } return true; } }