您的位置:首页 > 编程学习 > > 正文

phpredis怎么测试成功(PHP+redis实现的限制抢购防止商品超发功能详解)

更多 时间:2021-10-21 07:34:55 类别:编程学习 浏览量:775

phpredis怎么测试成功

PHP+redis实现的限制抢购防止商品超发功能详解

本文实例讲述了PHP+redis实现的限制抢购防止商品超发功能。分享给大家供大家参考,具体如下:

  • redis不仅仅是单纯的缓存,它还有一些特殊的功能,在一些特殊场景上很好用。redis中key的原子自增incrby和判断key不存在再写入的setnx方法,可以有效的防止超发。
  • 下面使用两个不同的方式来说明利用redis做商品购买库存数量限制。
  • 业务场景很简单,就是限制抢购5个商品,模拟并发请求抢购商品,每抢购一次对应redis中的key值增加一次,通过判断限购的数量来限制抢购,抢购成功写入成功日志,失败写入失败的信息记录,通过记录的数量来判断是否超发。

文件index.php

  • ?
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • <?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(empty($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

  • ?
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • <?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

  • ?
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • <?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方法

  • ?
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • [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方法日志分析

  • ?
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • [root@localhost log]# less -N way1.log
  •    1 抢到商品
  •    2 抢到商品
  •    3 抢到商品
  •    4 抢到商品
  •    5 抢到商品
  •    6 抢到商品
  •    7 没有抢到商品
  •    8 没有抢到商品
  •    9 没有抢到商品
  •    10 没有抢到商品
  •    11 没有抢到商品
  •    12 没有抢到商品
  • 观察日志发现 抢到商品的记录有6条超过正常的5条,说明超发了

    2.ab工具并发测试way2方法

  • ?
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • [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方法日志分析

  • ?
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • [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的在这方面就体现优势了。

    完整代码github地址

    希望本文所述对大家PHP程序设计有所帮助。

    原文链接:https://www.cnblogs.com/lisqiong/p/10223470.html

    标签:PHP redis 抢购
    您可能感兴趣