lock($key)) { * throw new Exception('error'); * } */ class RedisLock extends BaseObject { use StaticInstanceTrait; /** * 前缀 */ const KEY_PREFIX = 'BonusRedisLock:'; /** * 重试次数,0:无限重试 * @var int */ public $retryCount = 0; /** * 获取锁失败重试等待的时间,微妙 ,1ms=1000us * @var int */ public $retryInterval = 100000; /** * 获取锁失败,是否重试 * @var bool */ public $retry = true; /** * 锁的超时时间,防止死锁发生,应该是业务的最大处理时间 * @var int */ public $expire = 5; /** * Redis 对象 * @var null */ public $redis = null; /** * @inheritdoc */ public function init() { parent::init(); } /** * 获取redis对象 * @return mixed|null */ public function getRedis(){ if(!is_null($this->redis)){ return $this->redis; } $this->redis = Yii::$app->redis; return $this->redis; } /** * @return float */ public static function microTime() { // 获取当前毫秒时间戳 list ($s1, $s2) = explode(' ', microtime()); $currentTime = (float) sprintf('%.0f', (floatval($s1) + floatval($s2)) * 1000); return $currentTime; } /** * @param $key * @return string */ public static function getKey($key){ return self::KEY_PREFIX . $key; } /** * 加锁 * @param $key * @return bool */ public function lock($key) { $count = 0; $key = self::getKey($key); while (true) { $nowTime = self::microtime(); $lockValue = self::microtime() + $this->expire; $lock = $this->getRedis()->setnx($key, $lockValue); if (!empty($lock) || ($this->getRedis()->get($key) < $nowTime && $this->getRedis()->getset($key, $lockValue) < $nowTime )) { $this->getRedis()->expire($key, $this->expire); return true; } elseif ($this->retry && (($this->retryCount > 0 && ++$count < $this->retryCount) || ($this->retryCount == 0))) { usleep($this->retryInterval); } else { break; } } return false; } /** * 解锁 * @param $key * @return bool */ public function unlock($key) { $key = self::getKey($key); if ($this->getRedis()->ttl($key)) { return $this->getRedis()->del($key); } return true; } }