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

redis不仅仅是单纯的缓存,它还有一些特殊的功能,在一些特殊场景上很好用。redis中key的原子自增incrby和判断key不存在再写入的setnx方法,可以有效的防止超发。

下面使用两个不同的方式来说明利用redis做商品购买库存数量限制。

业务场景很简单,就是限制抢购5个商品,模拟并发请求抢购商品,每抢购一次对应redis中的key值增加一次,通过判断限购的数量来限制抢购,抢购成功写入成功日志,失败写入失败的信息记录,通过记录的数量来判断是否超发。

文件index.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

/**

* @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

//获取商品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

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

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的在这方面就体现优势了。

希望与广大网友互动??

点此进行留言吧!

php如何防止超发,PHP+redis实现的限制抢购防止商品超发功能详解相关推荐

  1. mysql防止超发_PHP+redis实现的限制抢购防止商品超发功能详解

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

  2. redis+php微博,redis+php实现微博(三)微博列表功能详解

    本文实例讲述了redis+php实现微博列表功能.分享给大家供大家参考,具体如下: 个人主页显示微博列表(自己及关注人的微博列表) /*获取最新的50微博信息列表,列出自己发布的微博及我关注用户的微博 ...

  3. redis stream持久化_Beetlex.Redis之Stream功能详解

    原标题:Beetlex.Redis之Stream功能详解 有一段时间没有写文章,techempower的测试规则评分竟然发生了变化,只能忘着补充一下占比权重最多的数据更新示例了和深入设计一下组件模块化 ...

  4. 超轻量级DI容器框架Google Guice与Spring框架的区别教程详解及其demo代码片段分享...

    超轻量级DI容器框架Google Guice与Spring框架的区别教程详解及其demo代码片段分享 DI框架 Google-Guice入门介绍 转载于:https://www.cnblogs.com ...

  5. python微信自动发消息_Python使用微信itchat接口实现查看自己微信的信息功能详解...

    Python使用微信itchat接口实现查看自己微信的信息功能详解 发布时间:2020-09-09 04:20:11 来源:脚本之家 阅读:134 本文实例讲述了Python使用微信itchat接口实 ...

  6. redis源码阅读-持久化之aof与aof重写详解

    aof相关配置 aof-rewrite-incremental-fsync yes # aof 开关,默认是关闭的,改为yes表示开启 appendonly no # aof的文件名,默认 appen ...

  7. Redis数据类型使用场景及有序集合SortedSet底层实现详解

    Redis常用数据类型有字符串String.字典dict.列表List.集合Set.有序集合SortedSet,本文将简单介绍各数据类型及其使用场景,并重点剖析有序集合SortedSet的实现. Li ...

  8. Redis中五大基本数据类型和三种特殊数据类型详解

    目录 介绍 概念 基本命令 redis是单线程的 五大基本数据类型 String 命令 应用场景 List 命令 应用场景 Set 命令 应用场景 Hash 命令 应用场景 Zset 命令 应用场景 ...

  9. Linux redis安装教程,Linux 下redis5.0.0安装教程详解

    Linux redis5.0.0安装,教程如下所示: 1.从官网下载,然后传到服务器,tar -zxvf解压 2.进入redis ? 3.安装:make, (1)若提示:: gcc: Command ...

最新文章

  1. Spring MVC——ConverterltString, Dategt DEMO
  2. java 下载工具_java文件下载工具类
  3. linux修改su的PAM配置文件,linux pam安全认证模块su命令的安全隐患
  4. day4-mysql数据关系
  5. mybatis SqlMapConfig.xml
  6. WCF中使用自定义behavior提示错误的解决方法
  7. Asp.Net访问Oracle 数据库 执行SQL语句和调用存储过程
  8. python requests.get无法取出网页_Python requests获取网页常用方法解析
  9. HP ProLiant DL380 G6 服务器 - 清 BIOS 的方法
  10. windows server 2008 R2 SP1多国语言包官方下载
  11. 素数筛【埃筛,欧拉筛(线性筛)】
  12. 技能高考的计算机教室,2020湖北技能高考成绩查询时间
  13. 图中最深的根 (25分)
  14. Annotated Potholes Image Dataset下载
  15. android线程池!如何试出一个Android开发者真正的水平?内容太过真实
  16. 《23种设计模式之原型模式(2种实现)》
  17. 高山养羊也可以运用GPS卫星定位系统
  18. MP3格式转WAV格式
  19. 如何把计算机软件卸载干净
  20. 目前android版本最好,当前主流的7个手机系统,你认为哪个最好用?

热门文章

  1. BIEE汇总数据如何放在后面
  2. 最长子段和 11061008 谢子鸣
  3. 跟燕十八学习PHP-第十五天-php增删改查表数据
  4. 计算机系统NSX,2017款的讴歌NSX计算机维持的“战斗机”
  5. python123电脑登录不了_Python-用户登陆,密码失败3次,账户将被锁住(login)
  6. 【数据结构与算法】之深入解析“石子游戏”的求解思路与算法示例
  7. hive中如何进行按周计算
  8. 2020年第十一届蓝桥杯 - 省赛 - Python大学组 - C.跑步锻炼
  9. 315. Count of Smaller Numbers After Self 计算右侧小于当前元素的个数
  10. 使用pytz模块进行时区转换及时间计算