Home  >  Q&A  >  body text

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);
    }
仅有的幸福仅有的幸福2735 days ago580

reply all(1)I'll reply

  • 为情所困

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

    You don’t need the memory lock for the lottery. It should be possible to use a Redis queue or transaction and add a Mysql lock. .

    I don’t know if the memory lock you want is this:
    $lock = new CacheLock('key_name');
    $lock->lock();
    //logic here
    $lock->unlock();
    CacheLock process lock is mainly used for single-process cache acquisition when the cache fails to prevent excessive SQL requests from penetrating into the database. It is used to solve the lock control of PHP during concurrency and inter-process locking through file/eaccelerator. If not Use eaccelerator to process file locks, and generate locks with corresponding granularity in the corresponding directory. Using eaccelerator, processing is done in memory, and the performance is relatively high. Different locks are executed in parallel, similar to the row-level locks of mysql innodb.

    reply
    0
  • Cancelreply