laravel的緩存類的store的redis實現,位於命名空間
Illuminate\Cache\RedisStore
其中實現了LockProvider,可獲取鎖實例,鎖實例為Illuminate\Cache\RedisLock類的實例,RedisLock類是Illuminate\Cache\Lock抽象類的實現
調用方法get()獲取鎖時(RedisLock->get()),首先調用$this->acquire(),具體代碼為
public function acquire()
{
$result = $this->redis->setnx($this->name, $this->owner);
if ($result === 1 && $this->seconds > 0) {
$this->redis->expire($this->name, $this->seconds);
}
return $result === 1;
}
其中使用redis的setnx命令,只有當key不存在時才能設置成功,通過此種方式實現分布式鎖的獲取,當get()方法中傳入過期時間(秒數)時,此時會設置過期時間,以避免意外造成死鎖的情況
當需要等待鎖釋放時,可以使用這個類中的block方法,該方法具體代碼為:
public function block($seconds, $callback = null)
{
$starting = $this->currentTime();
while (! $this->acquire()) {
usleep(250 * 1000);
if ($this->currentTime() - $seconds >= $starting) {
throw new LockTimeoutException;
}
}
if (is_callable($callback)) {
try {
return $callback();
} finally {
$this->release();
}
}
return true;
}
可見該方法大約每秒嘗試獲取鎖4次,超時即報錯,其第二個參數為回調函數,當其有值時,執行完成后自動釋放鎖
當具體使用時,可直接利用門面類Illuminate\Support\Facades\Cache來進行操作,例如:
$lock = Cache::lock('lockName', 10);
來獲取鎖,前提是你的config('cache.default')的值為redis或memcached等支持鎖的驅動,如果使用了文件,數組等不支持鎖的驅動將會報錯,因為它們的store實現沒有實現LockContract接口
