有关redis中setnx实现锁

//一下是我在做钉钉开发时存储token的一段代码
public static function corp_access_token()
{
    //将jsapi_ticket存入redis
    $redis = new Redis();
    $redis->connect(self::$redis_config['host']);
    $redis->auth(self::$redis_config['auth']);
    $key        = 'access_token_val';       //要更新信息的缓存KEY
    $lockKey    = 'lock_'.$key; //设置锁KEY
    $lockExpire = 10; //设置锁的有效期为10秒
    //获取缓存信息
    $jsapi_val = $redis->get($key);
    //判断缓存中是否有数据
    if(empty($jsapi_val))
    {
        $status = TRUE;
        while ($status)
        {
            //设置锁值为当前时间戳 + 有效期
            $lockValue = time() + $lockExpire;
           //setnx:当需要设置的值存在时就会返回一个假,不存在是就会设置值,且返回设置的值;
            $lock = $redis->setnx($lockKey,$lockValue);
           //下面的判断是关键
           //为了防止用户在进入if语句后出现错误,而导致死锁(那么$lock就永远不会过期)
           那么需要加一个$redis->get($lockKey) < time()   但是这个时候所有的用户均可以进来,
          为了防止这个时候的并发情况出现,那么必须加$redis->getSet($lockKey, $lockValue) < time() 来避免;
         getSet是返回key的旧值且设置一个新值            
        if(!empty($lock) || ($redis->get($lockKey) < time() && $redis->getSet($lockKey, $lockValue) < time() ))            
         {
                $redis->expire($lockKey, $lockExpire);
                $params = array(
                    'corpid'     => parent::$config['corpid'],
                    'corpsecret' => parent::$config['corpsecret'],
                );
                $result = self::get('gettoken', $params, false);
                if (false !== $result) {
                    $redis->setex($key,6000,$result['access_token']);
                    return $result['access_token'];
                } else {
                   if($redis->ttl($lockKey)){
                    $redis->del($lockKey);
                     }
                    $status = FALSE;
                    return false;
                }
                
            }else{
                sleep(2);//等待2秒后再尝试执行操作防止过多请求
            }
        }
    }else{
        return $jsapi_val;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值