【redis】redis 单机锁 和 分布式锁

依然范儿特西
2019-01-21 / 0 评论 / 1,166 阅读 / 正在检测是否收录...

单机锁

<?php
require "vendor/autoload.php";

$client = new Predis\Client([
   'scheme' => 'tcp',
   'host'   => '127.0.0.1',
   'port'   => 6379,
]);

class RedisLock
{
   public $objRedis = null;
   public $timeout = 3;
   /**
    * @desc 设置redis实例
    *
    * @param obj object | redis实例
    */
   public function __construct($obj)
   {
       $this->objRedis = $obj;
   }

   /**
    * @desc 获取锁键名
    */
   public function getLockCacheKey($key)
   {
       return "lock_{$key}";
   }

   /**
    * @desc 获取锁
    *
    * @param key string | 要上锁的键名
    * @param timeout int | 上锁时间
    */
   public function getLock($key, $timeout = NULL)
   {
       $timeout = $timeout ? $timeout : $this->timeout;
       $lockCacheKey = $this->getLockCacheKey($key);
       $expireAt = time() + $timeout;
       $isGet = (bool)$this->objRedis->setnx($lockCacheKey, $expireAt);
       if ($isGet) {
           return $expireAt;
       }

       while (1) {
           usleep(10);
           $time = time();
           $oldExpire = $this->objRedis->get($lockCacheKey);
           if ($oldExpire >= $time) {
               continue;
           }
           $newExpire = $time + $timeout;
           $expireAt = $this->objRedis->getset($lockCacheKey, $newExpire);
           if ($oldExpire != $expireAt) {
               continue;
           }
           $isGet = $newExpire;
           break;
       }
       return $isGet;
   }

   /**
    * @desc 释放锁
    *
    * @param key string | 加锁的字段
    * @param newExpire int | 加锁的截止时间
    *
    * @return bool | 是否释放成功
    */
   public function releaseLock($key, $newExpire)
   {
       $lockCacheKey = $this->getLockCacheKey($key);
       if ($newExpire >= time()) {
           return $this->objRedis->del($lockCacheKey);
       }
       return true;
   }
}

$start_time = microtime(true);
$lock = new RedisLock($client);
$key = "name";
for ($i = 0; $i < 10000; $i++) {
   $newExpire = $lock->getLock($key);
   $num = $client->get($key);
   $num++;
   $client->set($key, $num);
   $lock->releaseLock($key, $newExpire);
}
$end_time = microtime(true);

echo "花费时间 : ". ($end_time - $start_time) . "\n";

分布式锁

官方原文:https://redis.io/topics/distlock

翻译:http://ifeve.com/redis-lock/

注意下,按照上面的官方文档,setnx 的正确写法是

SET resource_name my_random_value NX PX 30000
1

评论 (0)

取消