Crazy lens

接口高并发解决方案
1. 同服务器下, 使用文件锁机制 <?php /** * 用于解决PHP在并发时候的锁控制,不同的锁之间...
扫描右侧二维码阅读全文
02
2017/07

接口高并发解决方案

1. 同服务器下, 使用文件锁机制


<?php
/**
 * 用于解决PHP在并发时候的锁控制,不同的锁之间并行执行,类似mysql innodb的行级锁
 */
class FileLock {

    //文件锁存放路径
    private $path='/dev/shm';

    //文件句柄
    private $fp='';

    //锁文件
    private $lockFile='';

    /**
     * 构造函数
     * @param string $name 锁 KEY
     */
    public function __construct($name)
    {
        $this->lockFile=$this->path.md5($name).'.lock';
    }
 
    /**
     * 加锁
     */
    public function lock()
    {
      $this->fp=fopen($this->lockFile, 'a+');
      if($this->fp===false){
        return false;
      }
      register_shutdown_function(array($this, 'unlock'));

      return flock($this->fp, LOCK_EX);//获取独占锁
    }
     
    /**
     * 解锁 (尽量手动解锁)
     */
    public function unlock()
    {
      if($this->fp!==false){
         @flock($this->fp,LOCK_UN);
         clearstatcache();
      }
      @fclose($this->fp);
      @unlink($this->lockFile);
    }
}

2. 多服务器下, 使用redis incr 机制 (判断incr 返回值是否为1 不为1 则die)

<?php
namespace Lock;

use handler\redisHandler;

class redisLock
{
    const KEY_LOCK = 'lock:%s:%s'; // tag uid

    private $lockey = '';

    private function __construct($tag, $uid)
    {
        $this->lockey = sprintf(self::KEY_LOCK, $tag, $uid);
    }

    public static function instance($tag, $uid)
    {
        $self = new self($tag, $uid);

        return $self->lock();
    }

    public function lock()
    {
        $incr = redisHandler::getRedisLock()->incr($this->lockey);
        if ($incr != 1) {
            return false;
        }
        redisHandler::getRedisLock()->expire($this->lockey, 10);
        register_shutdown_function(array($this, 'unlock'));

        return true;
    }

    public function unlock()
    {
        return redisHandler::getRedisLock()->pexpire($this->lockey, 1);
    }
}

redisHandler::getRedisLock 是redis单例模式实例

最后修改:2017 年 07 月 02 日 10 : 11 PM
如果觉得我的文章对你有用,请随意赞赏

发表评论