PHP使用redis实现分布式锁
原创话不多说直接上代码
$redisLock = Redis::lock(key, value, 5);//key使用商品id,value使用用户id拼接时间戳和随机字符
try {
//获取锁:适用于n个人抢1个商品的场景,避免出现多个人抢成功。
if (!$redisLock->acquire()) {
throw new Exception(手慢了,已被领取);
}
//自旋锁:适用于n个人抢m个商品,避免出现超卖(即实际卖出数量大于m个)问题
//参数1为获取锁的次数,参数2为获取锁的间隔时间。
/*if (!$redisLock->spin(3, 0.5)) {
throw new Exception(网络繁忙,请稍后再试);
}*/
$tr = DB::beginTransaction();
try {
//业务处理
$tr->commit();
} catch (yiidbException $e) {
$tr->rollBack();
throw new Exception($e->getMessage());
}
} finally {
//释放锁
$redisLock->release();
}
类Redis:
class Redis
{
/**
* @param string $db
* @return yii
edisConnection
*/
public static function connection(string $db = redis)
{
return app()->{$db};
}
/**
* @param $name
* @param $owner
* @param int $seconds
* @param string $db
* @return Lock
*/
public static function lock($name, $owner, int $seconds, string $db = redis)
{
return new Lock($name, $owner, $seconds, self::connection($db));
}
}
类Lock:
class Lock
{
private $key;
private $value;
private $seconds;
private $redis;
/**
* RedisLock constructor.
* @param $key
* @param $value
* @param int $seconds 过期秒数
* @param yii
edisConnection $redis 指定的redis
*/
public function __construct($key, $value, int $seconds, $redis)
{
$this->key = lock: . $key;
$this->value = $value;
$this->seconds = $seconds;
$this->redis = $redis;
}
/**
* 获取锁
* @return bool
*/
public function acquire()
{
if ($this->seconds) {
return (bool)$this->redis->set($this->key, $this->value, ex, $this->seconds, nx);
}
return (bool)$this->redis->setnx($this->key, $this->value);
}
/**
* 自旋锁
* @param int $spinTimes 自旋次数
* @param int|float $spinSeconds 间隔秒数
* @return bool
*/
public function spin(int $spinTimes = 2, $spinSeconds = 0.5)
{
if (is_float($spinSeconds)) {
$microSeconds = intval(fmod($spinSeconds, 1) * 1000000);
$spinSeconds = intval($spinSeconds);
}
while ($spinTimes > 0) {
$lock = self::acquire();
if ($lock || 0 == --$spinTimes) {
return $lock;
}
if ($spinSeconds) {
sleep($spinSeconds);
}
if (isset($microSeconds)) {
usleep($microSeconds);
}
}
return false;
}
/**
* 释放锁
* @return bool
*/
public function release()
{
return (bool)$this->redis->eval(LuaScript::UNLOCK, 1, $this->key, $this->value);
}
}
类LuaScript:
class LuaScript
{
const UNLOCK = <<
版权声明
所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除