redis實現分佈式鎖

<?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;
    }

}
相關文章
相關標籤/搜索