基于redis的分布式锁
<?php /** * 基于redis的分布式锁 * * 参考开源代码: * http://nleach.com/post/31299575840/redis-mutex-in-php * * https://gist.github.com/nickyleach/3694555 */ pc_base::load_sys_class('cache_redis', '', 0); class dist_key_redis { //锁的超时时间 const TIMEOUT = 20; const SLEEP = 100000; /** * Stores the expire time of the currently held lock * 当前锁的过期时间 * @var int */ protected static $expire; public static function getRedis() { return new cache_redis(); } /** * Gets a lock or waits for it to become available * 获得锁,如果锁被占用,阻塞,直到获得锁或者超时 * * 如果$timeout参数为0,则立即返回锁。 * * @param string $key * @param int $timeout Time to wait for the key (seconds) * @return boolean 成功,true;失败,false */ public static function lock($key, $timeout = null){ if(!$key) { return false; } $start = time(); $redis = self::getRedis(); do{ self::$expire = self::timeout(); if($acquired = ($redis->setnx("Lock:{$key}", self::$expire))) { break; } if($acquired = (self::recover($key))) { break; } if($timeout === 0) { //如果超时时间为0,即为 break; } usleep(self::SLEEP); } while(!is_numeric($timeout) || time() < $start + $timeout); if(!$acquired) { //超时 return false; } return true; } /** * Releases the lock * 释放锁 * @param mixed $key Item to lock * @throws LockException If the key is invalid */ public static function release($key){ if(!$key) { return false; } $redis = self::getRedis(); // Only release the lock if it hasn't expired if(self::$expire > time()) { $redis->del("Lock:{$key}"); } } /** * Generates an expire time based on the current time * @return int timeout */ protected static function timeout(){ return (int) (time() + self::TIMEOUT + 1); } /** * Recover an abandoned lock * @param mixed $key Item to lock * @return bool Was the lock acquired? */ protected static function recover($key){ $redis = self::getRedis(); if(($lockTimeout = $redis->get("Lock:{$key}")) > time()) { //锁还没有过期 return false; } $timeout = self::timeout(); $currentTimeout = $redis->getset("Lock:{$key}", $timeout); if($currentTimeout != $lockTimeout) { return false; } self::$expire = $timeout; return true; } } ?>