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

本文实例讲述了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的在这方面就体现优势了。

完整代码github地址

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

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

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

本文地址: http://www.cppcns.com/wangluo/php/274899.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值