雨的味道

【Redis】简单的redis锁实现

原代码:https://github.com/ronnylt/redlock-php


“优化”后的代码:

/**
 * redis锁
 */
class RedisLock
{
    /** @var int $retryDelay */
    private $retryDelay;
    
    /** @var int $retryCount */
    private $retryCount;
    
    /** @var float $clockDriftFactor */
    private $clockDriftFactor = 0.01;
    
    /** @var \Redis */
    private $redis;
    
    /**
     * RedisLock constructor.
     * @param \Redis $redis
     * @param int $retryDelay
     * @param int $retryCount
     */
    function __construct($redis, $retryDelay = 200, $retryCount = 3)
    {
        $this->redis = $redis;
        
        $this->retryDelay = $retryDelay;
        $this->retryCount = $retryCount;
    }
    
    /**
     * @param string $resource
     * @param int $ttl 单位:毫秒
     * @return array|bool 返回钥匙信息
     */
    public function lock($resource, $ttl = 5000)
    {
        $token = uniqid();
        $retry = $this->retryCount;
        
        do {
            $startTime = microtime(true) * 1000;
        
            if (!$this->lockInstance($this->redis, $resource, $token, $ttl)) {
                return false;
            }
            
            $drift = ($ttl * $this->clockDriftFactor) + 2;
            
            $validityTime = $ttl - (microtime(true) * 1000 - $startTime) - $drift;
            
            if ($validityTime > 0) {
                return [
                        'validity' => $validityTime,
                        'resource' => $resource,
                        'token' => $token,
                    ];
            } else {
                $this->unlockInstance($this->redis, $resource, $token);
            }
            
            $delay = mt_rand(floor($this->retryDelay / 2), $this->retryDelay);
            usleep($delay * 1000);
            
            $retry--;
        
        } while ($retry > 0);
        
        return false;
    }
    
    /**
         * 参数是钥匙信息
         *
         * @param array $lock
         */
    public function unlock(array $lock)
    {
        $resource = $lock['resource'];
        $token = $lock['token'];
        
        $this->unlockInstance($this->redis, $resource, $token);
    }
    
    private function lockInstance($instance, $resource, $token, $ttl)
    {
        return $instance->set($resource, $token, ['NX', 'PX' => $ttl]);
    }
    
    private function unlockInstance($instance, $resource, $token)
    {
        $script = '
        if redis.call("GET", KEYS[1]) == ARGV[1] then
            return redis.call("DEL", KEYS[1])
        else
            return 0
        end
        ';
        return $instance->eval($script, [$resource, $token], 1);
    }
}



«   2023年1月   »
1
2345678
9101112131415
16171819202122
23242526272829
3031
网站分类
搜索
最新留言
文章归档
网站收藏
友情链接
  • RainbowSoft Studio Z-Blog
  • 订阅本站的 RSS 2.0 新闻聚合

Powered By Z-BlogPHP 1.5.1 Zero Theme By 爱墙纸

百度资讯综合思念体对有机生命接触用人形终端界面 那就是
晋ICP备15000230号-1