搜索

首页  >  问答  >  正文

redis - PHP抽奖活动加内存锁,原理是什么?

PHP抽奖活动加内存锁,原理是什么?如何实现?

    public function acquire($key) {
        //如果需要同时获取两个锁
        if ( is_array($key) && count($key) == 2 ) {
            while (TRUE) {
                $res = array();
                foreach($key as $k => $v) {
                    $res[$k] = $this->acquire($v);
                    if ( !$res[$k] ) {
                        break;
                    }
                }
                //若第一个锁未拿到则直接返回
                if ( !$res[0] ) {
                    $err = new SysErr(System::MEMCACHE_ACQUIRE_LOCK_ERROR);
                    ErrorHandle::throwErr($err);
                } elseif( !$res[1] ) {
                    //释放第一个锁,等待然后重试
                    $this->release($key[0]);
                    usleep(LockConfig::LOCK_TIMEWAIT);
                } else {
                    return TRUE;
                }
            }
        } else {
            $lock_key = LockConfig::LOCK_PREFIX . $key;
            $i = 0;
            do {
                $lock = $this->_memcache->add( $lock_key, 1, LockConfig::LOCK_TIMEOUT );
                //如果第一次没有获取到锁则等待指定时间后重试
                if ($i > 0) {
                    usleep(LockConfig::LOCK_TIMEWAIT);
                }
                $i++;
                //超过重试次数后退出
                if ($i > LockConfig::LOCK_RETRY_TIMES) {
                    $err = new SysErr(System::MEMCACHE_ACQUIRE_LOCK_ERROR);
                    ErrorHandle::throwErr($err);
                }
            } while( !$lock );

            // 记录log
            if ($i > 1) {
                LogHelper::warning('lock.log', "Acquire lock '{$lock_key}' for {$i} times");
            }
            return $lock;
        }
    }
    
    
      /**
     * 释放内存锁
     *
     * @param  string $key 内存锁去除前缀后的key值
     * @return bool        释放成功返回TRUE
     */
    public function release($key) {
        $lock_key = LockConfig::LOCK_PREFIX . $key;
        return $this->_memcache->delete($lock_key);
    }
仅有的幸福仅有的幸福2756 天前607

全部回复(1)我来回复

  • 为情所困

    为情所困2017-05-16 13:11:23

    抽奖用不到内存锁吧。用个Redis队列或者事务加Mysql的锁应该可以了吧。。

    你要的内存锁不知道是不是这个:
    $lock = new CacheLock('key_name');
    $lock->lock();
    //logic here
    $lock->unlock();
    CacheLock 进程锁,主要用来进行cache失效时的单进程cache获取,防止过多的SQL请求穿透到数据库
    用于解决PHP在并发时候的锁控制,通过文件/eaccelerator进行进程间锁定
    如果没有使用eaccelerator则进行进行文件锁处理,会做对应目录下产生对应粒度的锁
    使用了eaccelerator则在内存中处理,性能相对较高
    不同的锁之间并行执行,类似mysql innodb的行级锁

    回复
    0
  • 取消回复