php通过标识加锁,PHP通过加锁实现并发情况下抢码功能
基于php语言使用加锁实现并发情况下抢码功能,特定时间段开放抢码并不允许开放的码重复:
需求:抢码功能
要求:
1、特定时间段才开放抢码;
2、每个时间段放开的码是有限的;
3、每个码不允许重复;
实现:
1、在不考虑并发的情况下实现:
function get_code($len){
$CHAR_ARR = array('1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','X','Y','Z','W','S','R','T');
$CHAR_ARR_LEN = count($CHAR_ARR) - 1;
$code = '';
while(--$len > 0){
$code .= $CHAR_ARR[rand(0,$CHAR_ARR_LEN)];
}
return $code;
}
$pdo = new PDO('mysql:host=localhost;dbname=ci_test','root','root');
//查询当前时间已发放验证码数量
$code_num_rs = $pdo->query("SELECT COUNT(*) as sum FROM code_test");
$code_num_arr = $code_num_rs->fetch(PDO::FETCH_ASSOC);
$code_num = $code_num_arr['sum'];
if($code_num < 1){
sleep(2); //暂停2秒
$code= get_code(6);
var_dump( $pdo->query("INSERT INTO code_test (code,create_time) VALUES ('$code',".time().")") );
}
上述代码默认满足当前是开放时间,和码是不重复的;
在不考虑并发情况下流程:
1)选查询当前数据库发放的验证码数量;
2)如果还有名额,则生成验证码,插入到数据库,返回验证码到客户端;
3)如果已满;则返回提示,已无名额;
2、并发情况下实现:
那么看下上面代码在并发情况下得到的结果:
测试并发,可以使用apache benchmark来测试,apache benchmark是APACHE旗下的HTTP SERVER的性能评测工具,通过cmd进入到apche的bin目录下,通过ab命令调用,如:ab -c 并发数量 -n 总访问量 url。
这样就是100个用户同事去抢1个名额,在查询的时候,每个用户都查询到还有一个名额,则会去生成验证码,插入数据库,返回验证码;这样就造成了验证码发多了。事实上,运行完该命令,数据库多了13条记录,而不是一条。
怎么避免这情况发生呢?
可以通过加排他锁来锁定判断到插入这个过程,保证这个判断流程任意一时间只有一个进程在运行。
实现如下:
//生成码
function get_code($len){
$CHAR_ARR = array('1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','X','Y','Z','W','S','R','T');
$CHAR_ARR_LEN = count($CHAR_ARR) - 1;
$code = '';
while(--$len > 0){
$code .= $CHAR_ARR[rand(0,$CHAR_ARR_LEN)];
}
return $code;
}
$pdo = new PDO('mysql:host=localhost;dbname=ci_test','root','root');
$fp = fopen('lock.txt','r');
//通过排他锁 锁定该过程
if(flock($fp,LOCK_EX)){
//查询当前时间已发放验证码数量
$code_num_rs = $pdo->query("SELECT COUNT(*) as sum FROM code_test");
$code_num_arr = $code_num_rs->fetch(PDO::FETCH_ASSOC);
$code_num = $code_num_arr['sum'];
if($code_num < 1){
sleep(2);
$code= get_code(6);
var_dump( $pdo->query("INSERT INTO code_test (code,create_time) VALUES ('$code',".time().")") );
}
flock($fp,LOCK_UN);
fclose($fp);
}
php通过标识加锁,PHP通过加锁实现并发情况下抢码功能相关推荐
- mysql不同情况下加锁类型实验 record lock 和 gap lock
首先确定RR级别下mysql的加锁规则(实验环境 mysql 8.0): 加锁的基本单位是 next-key lock.是一个前闭后开的区间,也是record lock 和 gap lock 的组合. ...
- 【高并发】高并发环境下诡异的加锁问题(你加的锁未必安全)
来自:冰河技术 声明 特此声明:文中有关支付宝账户的说明,只是用来举例,实际支付宝账户要比文中描述的复杂的多.也与文中描述的完全不同. 前言 很多网友留言说:在编写多线程并发程序时,我明明对共享资源加 ...
- shiro如何保证session不失效_请问在不加锁的情况下如何保证线程安全?
概念 compare and swap,解决多线程并行情况下使用锁造成性能损耗的一种机制,CAS操作包含三个操作数--内存位置(V).预期原值(A)和新值(B).如果内存位置的值与预期原值相匹配,那么 ...
- c++客户端发送加锁_MySQL语句加锁分析详解
前言 建立一个存储三国英雄的hero表: CREATE TABLE hero ( number INT, name VARCHAR(100), country varchar(100), PRIMAR ...
- POSIX 线程具体解释(3-相互排斥量:固定加锁层次/“试加锁-回退”)
有时一个相互排斥量是不够的: 比方: 当多个线程同一时候訪问一个队列结构时,你须要2个相互排斥量,一个用来保护队列头,一个用来保护队列元素内的数据. 当为多线程建立一个树结构时.你可能须要为每一个节点 ...
- 在高并发分布式情况下生成唯一标识id
做项目的时候经常会用id作为唯一标识. 但是当有这样一个需求出现的时候:工程分布式部署,要求抗住高并发.并且生成的id是根据时间自增的.解决这个问题有很多种方法,但是要选择一个性价比比较高的策略比较不 ...
- Python中字符串使用单引号、双引号标识和三引号标识,什么是三引号?什么情况下用哪种标识?
一.三引号是指三个单引号或者三个双引号: 二.Python中字符串如果以单引号.双引号标识和三引号标识开头,则字符串结尾也必须是对应的标识,不能变更: 三.三者的异同: 1.三者都是字符串,大部分情况 ...
- mysql innodb 读加锁,Mysql InnoDB加锁分析
在文章的开始,简单思考一个小问题:假如有一个SQL语句delete from T where id = 1,这条SQL在InnoDB中执行的时候数据库如何加锁的? 数据库的锁 要回答上面的问题,首先我 ...
- 【高并发】高并发场景下如何优化加锁方式?看完这篇我确实明白了!!
来自:冰河技术 写在前面 很多时候,我们在并发编程中,涉及到加锁操作时,对代码块的加锁操作真的合理吗?还有没有需要优化的地方呢? 前言 在<[高并发]优化加锁方式时竟然死锁了!!>一文中, ...
最新文章
- 资源 | 麻省理工学院开放 2018 自动驾驶课程
- java分析日志文件_java程序如何对监控软件的日志文件进行如下分析?
- python 只取数值_Python:你会生成列表吗?-- 列表生成式
- SAP Spartacus产品转盘页面(ProductCarousel)的产品数据批量加载实现细节
- C语言 指针数组-字符指针数组整型指针数组 char*s[3] int*a[5] 数组指针int(*p)[4]
- 什么是Servlet类
- java readpassword_Java Password.readPassword方法代碼示例
- asp.net 与donet(.net)的区别
- TangIDE游戏开发之70行代码实现打地鼠
- RHEL Linux 8.3 通过 BIND 实现 DNS 基本功能
- 南昌人武学院计算机室,【志愿者日记】南昌大学人武学院:用行动感染身边的人...
- python-turtle(海龟绘图)圣诞树
- the info.plist in the package must contain the CFBundleShortVersionString key.
- 七牛云测试域名过期了,全部图片下载方法
- 千层套路“千层饼”,论面试中的套路与反套路
- Trying to access array offset on value of type null
- 克莱因瓶四维空间猜想
- 用word2013发布csdn博客
- 读《洛克菲勒给儿子的38封信》有感
- Introduction to JavaScript(JavaScript简介)
热门文章
- Elasticsearch修改字段之别名,扩展数据迁移
- linux 升级centos7,Linux之从Centos 6.x 升级Centos7
- java单线程上锁_关于Java多线程编程锁优化的深入学习
- python 找质数的个数_用Python打造一款文件搜索工具,所有功能自己定义!
- docker 删除image_如何用两个小时入门 Docker?
- python三种变量方式_python2.x 3种变量形式调用
- js读写php文件,在js中如何读取本地文件
- mysql永远不用utf8_永远不要在 MySQL 中使用「utf8」
- 腾讯视频如何删除观看记录
- 搜狐视频开放平台的申请使用方法