redis加锁的方式

<?php
/**
 * Created by PhpStorm.
 * User: chelun
 * Date: 2018/12/26
 * Time: 下午8:15
 */

namespace App\Util;

use Illuminate\Support\Facades\Redis;

class RedisLock
{
    const LOCK_KEY = 'WRB_LOCK:';

    /**
     * @param string $redisInst
     * @return redis
     */
    public static function getRedis($redisInst = 'default')
    {
        return Redis::connection($redisInst);
    }

    /**
     * @param string $lockKey
     * @return bool
     */
    public static function lock($lockKey = '', $expire = 5, $forceLock = true)
    {
        $oriKey = $lockKey;
        $lockKey = self::LOCK_KEY.$oriKey;
        $redis = self::getRedis();
        $isLock = $redis->setnx($lockKey, time() + $expire);
        if(!$isLock)
        {
            $lockTime = $redis->get($lockKey);
            if(time() >= $lockTime)
            {
                self::unlock($oriKey);
                if($forceLock)
                {
                    $isLock = $redis->setnx($lockKey, time() + $expire);
                }
                else
                {
                    return true;
                }
            }
        }

        return $isLock ? true : false;
    }

    /**
     * @param $lockKey
     * @return bool
     */
    public static function unlock($lockKey)
    {
        $lockKey = self::LOCK_KEY.$lockKey;
        $redis = self::getRedis();
        $redis->del($lockKey);

        return true;
    }
}
<?php
/**
 * Created by PhpStorm.
 * User: chelun
 * Date: 2019/9/27
 * Time: 上午9:53
 */

namespace App\Common;


class CacheLock
{

    private $_cache = null;

    private $_key = '';

    private $_expire = 30;

    private $_isInstance = false;

    private $_isLocked = false;

    private $_autoUnLock = true;

    public function __construct($key)
    {
        if (empty($key))
        {
            throw new \Exception('new CacheLock($key) $key is not empty');
        }

        $this->_cache = app('redis');
        $this->_key = $this->cacheKey(__FILE__, $key);
        $this->_expire = ini_get('max_execution_time') > 0 ? ini_get('max_execution_time') : 30;
    }

    /**
     * 设定缓存的强制锁定时间,必须锁定足够时间才能解锁
     * @param int|number $sec
     * @throws Exception
     */
    public function setExpire($sec = 5)
    {
        $this->_autoUnLock = false;
        $this->_expire = $sec;
        if ($sec > 86400)
        {
            throw new \Exception('$sec is too large,more than 1 day');
        }
    }

    /**
     * 采用CAS乐观锁
     *
     * @throws Exception
     * @return boolean
     */
    public function lock()
    {
        if ($this->_isInstance)
        {
            throw new \Exception('每个CacheLock实例只能lock一次,当一个请求中需要多次锁定时,请分别实例化CacheLock类');
        }

        try
        {
            $this->_isLocked = true;
            $this->_isInstance = true;

            if ($this->_cache->exists($this->_key))
            {
                return $this->_isLocked;
            }

            $this->_cache->watch($this->_key);
            $val = $this->_cache->get($this->_key);
            if ($val !== false)
            {
                return $this->_isLocked;
            }

            $rst = $this->_cache->multi()
                ->incr($this->_key)
                ->expireAt($this->_key, time() + $this->_expire)
                ->exec();

            if ($rst !== false)
            {
                $this->_isLocked = false;
            }
            return $this->_isLocked;
        }
        catch (\Exception $e)
        {
            return true;
        }
    }

    /**
     * 返回ttl信息
     *
     */
    public function ttl()
    {
        return $this->_cache->ttl($this->_key);
    }

    /**
     * 释放锁,在特定情况下,手动释放
     * @return bool
     * @throws Exception
     */
    public function release()
    {
        if (!$this->_cache instanceof redis)
        {
            throw new \Exception('$this->_cache is not a redis instance');
        }
        $this->_cache->delete($this->_key);
        return true;
    }

    function cacheKey()
    {
        $args = func_get_args();
        return md5(__FILE__ . serialize($args));
    }

    /**
     * 自动释放锁,注意点:只有加锁的人自己才可以解锁
     */
    public function __destruct()
    {
        if (!$this->_isLocked && $this->_autoUnLock)
        {
            $this->_cache->delete($this->_key);
            $this->_cache->close();
        }
    }
}
发布了93 篇原创文章 · 获赞 2 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_32783703/article/details/103038007