PHP+redis实现的限制抢购防止商品超发功能详解
发布:smiling 来源: PHP粉丝网 添加日期:2021-12-19 11:55:11 浏览: 评论:0
本文实例讲述了PHP+redis实现的限制抢购防止商品超发功能,分享给大家供大家参考,具体如下:
redis不仅仅是单纯的缓存,它还有一些特殊的功能,在一些特殊场景上很好用,redis中key的原子自增incrby和判断key不存在再写入的setnx方法,可以有效的防止超发。
下面使用两个不同的方式来说明利用redis做商品购买库存数量限制。
业务场景很简单,就是限制抢购5个商品,模拟并发请求抢购商品,每抢购一次对应redis中的key值增加一次,通过判断限购的数量来限制抢购,抢购成功写入成功日志,失败写入失败的信息记录,通过记录的数量来判断是否超发。
文件index.php
- <?php
- require_once './myRedis.php';
- require_once './function.php';
- class sendAward{
- public $conf = [];
- const V1 = 'way1';//版本一
- const V2 = 'way2';//版本二
- const AMOUNTLIMIT = 5;//抢购数量限制
- const INCRAMOUNT = 1;//redis递增数量值
- //初始化调用对应方法执行商品发放
- public function __construct($conf,$type){
- $this->conf = $conf;
- if(emptyempty($type))
- return '';
- if($type==self::V1){
- $this->way1(self::V1);
- }elseif($type==self::V2){
- $this->way2(self::V2);
- }else{
- return '';
- }
- }
- //抢购商品方式一
- protected function way1($v){
- $redis = new myRedis($this->conf);
- $keyNmae = getKeyName($v);
- if(!$redis->exists($keyNmae)){
- $redis->set($keyNmae,0);
- }
- $currAmount = $redis->get($keyNmae);
- if(($currAmount+self::INCRAMOUNT)>self::AMOUNTLIMIT){
- writeLog("没有抢到商品",$v);
- return;
- }
- $redis->incrby($keyNmae,self::INCRAMOUNT);
- writeLog("抢到商品",$v);
- }
- //抢购商品方式二
- protected function way2($v){
- $redis = new myRedis($this->conf);
- $keyNmae = getKeyName($v);
- if(!$redis->exists($keyNmae)){
- $redis->setnx($keyNmae,0);
- }
- if($redis->incrby($keyNmae,self::INCRAMOUNT) > self::AMOUNTLIMIT){
- writeLog("没有抢到商品",$v);
- return;
- }
- writeLog("抢到商品",$v);
- }
- }
- //实例化调用对应执行方法
- $type = isset($_GET['v'])?$_GET['v']:'way1';
- $conf = [
- 'host'=>'192.168.0.214','port'=>'6379',
- 'auth'=>'test','db'=>2,
- ];
- new sendAward($conf,$type);
文件myRedis.php
- <?php
- /**
- * @desc 自定义redis操作类
- * **/
- class myRedis{
- public $handler = NULL;
- public function __construct($conf){
- $this->handler = new Redis();
- $this->handler->connect($conf['host'], $conf['port']); //连接Redis
- //设置密码
- if(isset($conf['auth'])){
- $this->handler->auth($conf['auth']); //密码验证
- }
- //选择数据库
- if(isset($conf['db'])){
- $this->handler->select($conf['db']);//选择数据库2
- }else{
- $this->handler->select(0);//默认选择0库
- }
- }
- //获取key的值
- public function get($name){
- return $this->handler->get($name);
- }
- //设置key的值
- public function set($name,$value){
- return $this->handler->set($name,$value);
- }
- //判断key是否存在
- public function exists($key){
- if($this->handler->exists($key)){
- return true;
- }
- return false;
- }
- //当key不存在的设置key的值,存在则不设置
- public function setnx($key,$value){
- return $this->handler->setnx($key,$value);
- }
- //将key的数值增加指定数值
- public function incrby($key,$value){
- return $this->handler->incrBy($key,$value);
- }
- }
文件function.php
- <?php
- //获取商品key名称
- function getKeyName($v)
- {
- return "send_goods_".$v;
- }
- //日志写入方法
- function writeLog($msg,$v)
- {
- $log = $msg.PHP_EOL;
- file_put_contents("log/$v.log",$log,FILE_APPEND);
- }
1.ab工具并发测试way1方法
- [root@localhost oversend]# ab -c 100 -n 200 http://192.168.0.213:8083/index.php?v=way1
- This is ApacheBench, Version 2.3 <$Revision: 655654 $>
- Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
- Licensed to The Apache Software Foundation, http://www.apache.org/
- Benchmarking 192.168.0.213 (be patient)
- Completed 100 requests
- Completed 200 requests
- Finished 200 requests
- Server Software: nginx
- Server Hostname: 192.168.0.213
- Server Port: 8083
- Document Path: /index.php?v=way1
- Document Length: 0 bytes
- Concurrency Level: 100
- Time taken for tests: 0.089 seconds
- Complete requests: 200
- Failed requests: 0
- Write errors: 0
- Total transferred: 30600 bytes
- HTML transferred: 0 bytes
- Requests per second: 2243.13 [#/sec] (mean)
- Time per request: 44.581 [ms] (mean)
- Time per request: 0.446 [ms] (mean, across all concurrent requests)
- Transfer rate: 335.16 [Kbytes/sec] received
- Connection Times (ms)
- min mean[+/-sd] median max
- Connect: 0 6 2.2 5 17
- Processing: 2 28 16.3 25 55
- Waiting: 1 26 15.2 24 50
- Total: 5 34 16.3 30 60
- Percentage of the requests served within a certain time (ms)
- 50% 30
- 66% 35
- 75% 54
- 80% 56
- 90% 57
- 95% 60
- 98% 60
- 99% 60
- 100% 60 (longest request)
v1方法日志分析
- [root@localhost log]# less -N way1.log
- 1 抢到商品
- 2 抢到商品
- 3 抢到商品
- 4 抢到商品
- 5 抢到商品
- 6 抢到商品
- 7 没有抢到商品
- 8 没有抢到商品
- 9 没有抢到商品
- 10 没有抢到商品
- 11 没有抢到商品
- 12 没有抢到商品
观察日志发现 抢到商品的记录有6条超过正常的5条,说明超发了
2.ab工具并发测试way2方法
- [root@localhost oversend]# ab -c 100 -n 200 http://192.168.0.213:8083/index.php?v=way2
- This is ApacheBench, Version 2.3 <$Revision: 655654 $>
- Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
- Licensed to The Apache Software Foundation, http://www.apache.org/
- Benchmarking 192.168.0.213 (be patient)
- Completed 100 requests
- Completed 200 requests
- Finished 200 requests
- Server Software: nginx
- Server Hostname: 192.168.0.213
- Server Port: 8083
- Document Path: /index.php?v=way2
- Document Length: 0 bytes
- Concurrency Level: 100
- Time taken for tests: 0.087 seconds
- Complete requests: 200
- Failed requests: 0
- Write errors: 0
- Total transferred: 31059 bytes
- HTML transferred: 0 bytes
- Requests per second: 2311.68 [#/sec] (mean)
- Time per request: 43.259 [ms] (mean)
- Time per request: 0.433 [ms] (mean, across all concurrent requests)
- Transfer rate: 350.58 [Kbytes/sec] received
- Connection Times (ms)
- min mean[+/-sd] median max
- Connect: 0 6 5.4 5 13
- Processing: 3 31 16.6 30 70
- Waiting: 1 30 16.6 30 70
- Total: 5 37 18.5 32 82
- Percentage of the requests served within a certain time (ms)
- 50% 32
- 66% 41
- 75% 45
- 80% 50
- 90% 68
- 95% 80
- 98% 81
- 99% 82
- 100% 82 (longest request)
v2方法日志分析
- [root@localhost log]# less -N v2.log
- [root@localhost log]# less -N way2.log
- 1 抢到商品
- 2 抢到商品
- 3 抢到商品
- 4 抢到商品
- 5 没有抢到商品
- 6 抢到商品
- 7 没有抢到商品
- 8 没有抢到商品
- 9 没有抢到商品
- 10 没有抢到商品
总结:观察日志可知抢到商品的日志记录是5条并没有超发,说明利用这种方式可以限制住库存的数量。之所以超发是因为方法一中通过加法来判断限制条件的同时,并发一大,就会越过这个判断条件出现会超发,redis的在这方面就体现优势了。
Tags: PHP+redis PHP商品超发
相关文章
- ·PHP语言发展历史(2013-11-11)
推荐文章
热门文章
最新评论文章
- 写给考虑创业的年轻程序员(10)
- PHP新手上路(一)(7)
- 惹恼程序员的十件事(5)
- PHP邮件发送例子,已测试成功(5)
- 致初学者:PHP比ASP优秀的七个理由(4)
- PHP会被淘汰吗?(4)
- PHP新手上路(四)(4)
- 如何去学习PHP?(2)
- 简单入门级php分页代码(2)
- php中邮箱email 电话等格式的验证(2)