redis+lua创建锁机制类

<?php


namespace App\Http\Controllers\lock;


use App\Http\Controllers\Controller;

class LockController extends Controller
{
    private $redis;
    private $lockId; //记录加锁客户端的id

    public function __construct($redis)
    {
        $this->redis = $redis;
    }

    /**
     * @param string $scene  业务场景
     * @param int $expire    锁过期时间
     * @param int $retry     等待尝试次数
     * @param int $sleep     等待时间
     * @return bool
     */
    public function lock($scene='seckill',$expire=5,$retry=5,$sleep=1000000){
        //同一时刻只能有一个用户持有锁,并且不能出现死锁
        $res=false;
        while($retry-- > 0){
            $value=uniqid();//生成不重复的字符串
            $res=$this->redis->set($scene,$value,['NX','EX'=>$expire]);
            if($res){
                $this->lockId[$scene] = $value;
                break;
            }
            var_dump('尝试获取锁'.PHP_EOL) ;
            usleep($sleep);
        }

        return $res;
    }

    public function unlock($scene){
        $script=<<<LUA
            local key=KEYS[1];
            local value=ARGV[1];
            if(redis.call('get',key) == value)
            then
                return redis.call('del',key)
            end
LUA;

        //能够删除自己的锁,而不应该删除别人的锁
        if(isset($this->lockId[$scene])){
            $id = $this->lockId[$scene];
//            $value = $this->redis->get($scene);
//
//            if($value == $id){
//                return $this->redis->del($scene);
//            }
            $this->redis->eval($script,[$scene,$id]);
        }
        return false;
    }
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值