我是靠谱客的博主 鳗鱼电脑,最近开发中收集的这篇文章主要介绍php lock_nb 单进程,php 并发控制中的独占锁,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

并发大家都知道是什么情况,这里说的是并发多个请求抢占同一个资源,直接上实例吧

请求:index.php?mod=a&action=b&taskid=6

处理:

$key = "a_b::".$uid.'_'.$taskid;

$v = $redis->get($key);

if($v == 1){

$redis->setex($key,10,1);

//处理逻辑省略

}

逻辑看来还可以,结果发现数据库中写入了两个同样的请求结果,我看了记录的时间戳,天!居然是同一秒.

我用microtime(true) log一下两个请求的时间差居然相差了0.0001s,就是说$redis->setex($key,10,1);还没执行成功 第二个请求已经get到跟第一个请求一样的结果。这不就是传说中的并发抢占资源。这中情况 听过很多,在开发过程中也没刻意去模拟实验过

第一反应就是要给处理过程加事务(数据库是mysql innoDB),加事务的结果就是 第一个请求成功了 第二个请求会执行到后面捡查发现重了会回滚

其实mysql事务在保证数据一致性上是很ok的,但是通过回滚来保证唯一资源独占代价太大,做过mysql事务测试测同学都知道,事务中的insert是已经插进去了,回滚之后才删掉的。

还有一个选择就是php中的文件独占锁,那就是说这情况下我要新建 用户数 * 任务数的文件来实现每个请求资源的独占,如果独占资源较少的话可选的解决办法:

/**

* 加锁

*/

public function file_lock($filename){

$fp_key = sha1($filename);

$this->fps[$fp_key] = fopen($filename, 'w+');

if($this->fps[$fp_key]){

return flock($this->fps[$fp_key], LOCK_EX|LOCK_NB);

}

return false;

}

/**

* 解锁

*/

public function file_unlock($filename){

$fp_key = sha1($filename);

if($this->fps[$fp_key] ){

flock($this->fps[$fp_key] , LOCK_UN);

fclose($this->fps[$fp_key] );

}

}

发现$redis->setnx()可以提供原子操作的状态:相同的key执行setnx之后没过期或者没del,再执行会返回false。这就让两个以上的并发请求得到控制必须成功获取锁才能继续。

下面的是我实现的代码:

/**

* 加锁

*/

public function task_lock($taskid){

$expire = 2;

$lock_key ='task_get_reward_'.$this->uid.'_'.$taskid;

$lock = $this->redis->setNX($lock_key , time());//设当前时间

if($lock){

$this->redis->expire($lock_key, $expire); //如果没执行完 2s锁失效

}

if(!$lock){//如果获取锁失败 检查时间

$time = $this->redis->get($lock_key);

if(time() - $time >= $expire){//添加时间戳判断为了避免expire执行失败导致死锁 当然可以用redis自带的事务来保证

$this->redis->rm($lock_key);

}

$lock = $this->redis->setNX($lock_key , time());

if($lock){

$this->redis->expire($lock_key, $expire); //如果没执行完 2s锁失效

}

}

return $lock;

}

/**

* 解锁

*/

public function task_unlock($taskid){

$this->set_redis();

$lock_key = 'task_get_reward_'.$this->uid.'_'.$taskid;

$this->redis->rm($lock_key);

}

说明下setNX 和expire 这两个操作其实可以用redis事务来保证一致性

最后

以上就是鳗鱼电脑为你收集整理的php lock_nb 单进程,php 并发控制中的独占锁的全部内容,希望文章能够帮你解决php lock_nb 单进程,php 并发控制中的独占锁所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(38)

评论列表共有 0 条评论

立即
投稿
返回
顶部