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 并发控制中的独占锁相关推荐
- php独占登录,php并发控制中的独占锁
1.并发问题 并发大家都知道是什么情况,这里说的是并发多个请求抢占同一个资源,直接上实例吧 请求:index.php?mod=a&action=b&taskid=6 处理: $key ...
- Java开发技巧——并发控制中的乐观锁与悲观锁
1.为什么需要锁? 在多用户环境中,在同一时间可能会有多个用户新相同的记录,这会产生冲突.这就是的并发性问题. 2.典型的冲突类型: (1)丢失新:一个事务的新覆盖了其它事务的新结果,就是所谓的新丢失 ...
- 并发控制中的乐观锁与悲观锁
为什么需要锁(并发控制)? 在多用户环境中,在同一时间可能会有多个用户更新相同的记录,这会产生冲突.这就是著名的并发性问题. 典型的冲突有: (1)丢失更新:一个事务的更新覆盖了其它事务的更新结果,就 ...
- 聊聊数据库中的那些锁
背景 数据库中有一张叫后宫佳丽的表,每天都有几百万新的小姐姐插到表中,光阴荏苒,夜以继日,日久生情,时间长了,表中就有了几十亿的小姐姐数据,看到几十亿的小姐姐,每到晚上,我可愁死了,这么多小姐姐,我翻 ...
- 数据库并发控制,选择乐观锁还是悲观锁?
出处:http://www.cnblogs.com/chenlulouis/ 今天,在这里,我们将讨论的是在实际生产过程中,对于并发控制你是选择乐观锁还是悲观锁.这两种锁各自的应用环境应该怎样选择? ...
- java 共享锁 独占锁_java中的公平锁、非公平锁、可重入锁、递归锁、自旋锁、独占锁和共享锁...
一.公平锁与非公平锁 1.1 概述 公平锁:是指多个线程按照申请锁的顺序来获取锁. 非公平锁:是指在多线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取到锁,在高并发的情 ...
- mysql 的独占锁和排它锁_数据库中的共享锁与排他锁
摘要: 能修改数据.为什么要加锁很多人都知道,锁是用来解决并发问题的,那么什么是并发问题呢?并发情况下,不加锁会有什么问题呢?拿生活中的洗手间举例子,每个洗手间都会有一个门,并且是可以上锁的,当我们进 ...
- Java中的锁机制 -- 乐观锁、悲观锁、自旋锁、可重入锁、读写锁、公平锁、非公平锁、共享锁、独占锁、重量级锁、轻量级锁、偏向锁、分段锁、互斥锁、同步锁、死锁、锁粗化、锁消除
文章目录 1. Java中的锁机制 1.1 乐观锁 1.2 悲观锁 1.3 自旋锁 1.4 可重入锁(递归锁) 1.5 读写锁 1.6 公平锁 1.7 非公平锁 1.8 共享锁 1.9 独占锁 1.1 ...
- 把MySQL中的各种锁及其原理都画出来
疫情期间在家工作时,同事使用了 insert into on duplicate key update 语句进行插入去重,但是在测试过程中发生了死锁现象: ERROR 1213 (40001): De ...
最新文章
- Mac 安装多个版本jdk
- matlab 函数 向量参数,Scipy integrate(quad,quadration,nquad)不能集成向量参数化函数?等效函数(MATLAB works)...
- Dockerfile中的保留字指令讲解
- 蓝牙打印和网口打印的实现
- [论文阅读] Annotation-Efficient Cell Counting
- ASP.NET分类信息站全站制作视频教程5(AJAX+SQLITE+生成静态HTML)
- AR引擎vuforia源码分析、中文注释(2)用手势控制来与模型简单交互
- Ubuntu默认Python版本选择
- 俄罗斯方块、纯前端实现俄罗斯方块、俄罗斯方块代码
- 非常好用的jdk帮助文档jdk1.8中文谷歌翻译
- pc企业微信hook接口,企业微信营销软件,企业微信群发
- NB-IOT (2)---移远BC26模块模组快速入门
- 5G 商用第三年:无人驾驶的“上山”与“下海”
- cad.net cad启动慢? cad2008启动慢? cad启动延迟? cad卡住? cad98%卡? 默认打印机!!
- 2016年全球超级计算机榜首是,中国神威·太湖之光荣登全球超级计算机500强榜首...
- 一文读懂什么是EPP、EDR、CWPP、HIDS及业内主流产品
- 金融借贷平台大数据风控解决方案
- wps在线预览接口_文档在线预览的实现
- Kubernetes kata-container 介绍
- Kubectl debug 调试容器
热门文章
- C语言小于n的素数,关于求N以内素数的一点小问题(N小于一亿)
- linux 版本信息 64位,Centos查看版本信息
- 【Oracle】DG中物理备库、快照备库的相互转换
- 编译Android源码致命错误解决方案
- nginx之206异常
- 本地Apache服务器访问时502 Server dropped connection 错误解决方法
- [PVE]解决 ProXmoX VE升级 apt-get update 报错的问题
- 如何取消选中单选按钮?
- ubuntu18.04下 c++安装opencv-3.4.6,c++安装opencv-3.4.9,clion配置opencv-3.4.6与 python安装 opencv-3.4.6
- 怎样通过ip查看linux密码,怎么根据linux根据ip地址查主机名