<?php
class Lock {
/**
* 单据锁默认超时时间(秒)
*/
const REDIS_LOCK_DEFAULT_EXPIRE_TIME = 86400;
protected $redis;
/**
* 初始化redis
* @param string $host redis主机
* @param int $prot 端口
* @return string $auth redis密码
*/
public function __construct($host, $prot, $auth) {
$this->redis = new \Redis();
$this->redis->connect($host, $prot);
if(!empty($auth)){
$this->redis->auth($auth);
}
}
/**
* 加锁
* @param string $scene 场景
* @param int $intExpireTime 锁过期时间(秒)
* @return bool|int 加锁成功返回唯一锁ID,加锁失败返回false
*/
public function lock($scene,$intExpireTime= self::REDIS_LOCK_DEFAULT_EXPIRE_TIME){
//参数校验
if (empty($scene) || $intExpireTime <= 0) {
return false;
}
//生成唯一ID,解锁需持有此ID
$lockId = uniqid();
//加锁(通过Redis setnx指令实现,从Redis 2.6.12开始,通过set指令可选参数也可以实现setnx,同时可原子化地设置超时时间)
$result = $this->redis->set($scene, $lockId, ['nx', 'ex'=>$intExpireTime]);
//加锁成功返回锁ID,加锁失败返回false
return $result ? $lockId : $result;
}
/**
* 解锁
* @param string $scene 场景
* @param int $lockId 锁唯一ID
* @return bool
*/
public function unLock($scene, $lockId){
//参数校验
if (empty($scene) || empty($lockId)) {
return false;
}
//监听Redis key防止在【比对lock id】与【解锁事务执行过程中】被修改或删除,提交事务后会自动取消监控,其他情况需手动解除监控
$this->redis->watch($scene);
//比对lock id
$result = $this->redis->get($scene);
if ($result === $lockId) {
//解锁
$this->redis->multi()->del($scene)->exec();
return true;
}
//取消监控
$this->redis->unwatch();
return false;
}
}
$lock = new Lock('127.0.0.1', 6379, '123456789');
$re = $lock->lock('test', 9999999);
var_dump($re);
echo '<hr/>';
$re2 = $lock->lock('test', 9999999);
var_dump($re2);
echo '<hr/>';
$re3 = $lock->unLock('test', '624567e95bc8c');
var_dump($re3);
php redis分布式锁
最新推荐文章于 2024-03-23 14:12:06 发布