侧边栏壁纸
博主头像
落叶人生博主等级

走进秋风,寻找秋天的落叶

  • 累计撰写 130562 篇文章
  • 累计创建 28 个标签
  • 累计收到 9 条评论
标签搜索

目 录CONTENT

文章目录

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

2022-06-26 星期日 / 0 评论 / 0 点赞 / 68 阅读 / 8752 字

本文实例讲述了PHP+redis实现的限制抢购防止商品超发功能。分享给大家供大家参考,具体如下: redis不仅仅是单纯的缓存,它还有一些特殊的功能,在一些特殊场景上很好用。redis中key的原子自增incrby和判

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

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

文件index.php

.
<?phprequire_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

.
<?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=way1This 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 requestsCompleted 200 requestsFinished 200 requestsServer Software:    nginxServer Hostname:    192.168.0.213Server Port:      8083Document Path:     /index.php?v=way1Document Length:    0 bytesConcurrency Level:   100Time taken for tests:  0.089 secondsComplete requests:   200Failed requests:    0Write errors:      0Total transferred:   30600 bytesHTML transferred:    0 bytesRequests 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] receivedConnection Times (ms)       min mean[+/-sd] median  maxConnect:    0  6  2.2   5   17Processing:   2  28 16.3   25   55Waiting:    1  26 15.2   24   50Total:     5  34 16.3   30   60Percentage 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=way2This 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 requestsCompleted 200 requestsFinished 200 requestsServer Software:    nginxServer Hostname:    192.168.0.213Server Port:      8083Document Path:     /index.php?v=way2Document Length:    0 bytesConcurrency Level:   100Time taken for tests:  0.087 secondsComplete requests:   200Failed requests:    0Write errors:      0Total transferred:   31059 bytesHTML transferred:    0 bytesRequests 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] receivedConnection Times (ms)       min mean[+/-sd] median  maxConnect:    0  6  5.4   5   13Processing:   3  31 16.6   30   70Waiting:    1  30 16.6   30   70Total:     5  37 18.5   32   82Percentage 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的在这方面就体现优势了。

.

完整代码github地址

更多关于PHP相关内容感兴趣的读者可查看本站专题:《php+redis数据库程序设计技巧总结》、《php面向对象程序设计入门教程》、《PHP基本语法入门教程》、《PHP数组(Array)操作技巧大全》、《php字符串(string)用法总结》、《php+mysql数据库操作入门教程》及《php常见数据库操作技巧汇总

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

广告 广告

评论区