下面测试2种抢购实现方案
首先数据库中一个很简单的表
DROP TABLE IF EXISTS `op_qiang`; CREATE TABLE `op_qiang` ( `id` int(10) NOT NULL AUTO_INCREMENT, `num` int(8) unsigned NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; INSERT INTO `op_qiang` (`id`, `num`) VALUES (1, 10);
op_qiang这个表中 ID为1的商品 库存数量为10
第一种方案 将mysql中,num这个字段 设置为 unsigned 表示这个字段不能为负数,如果减库存为负数了就会返回flase总而解决超卖问题。
//抢购 通过 mysql 字段设置 设为unsigned, 实现
public function sqla(){
$f = db('qiang')->where('id',1)->find();
$t = mt_rand(100,999999);
if($f['num']<=0){
exit("over");
}
$re = db('qiang')->where('id',1)->setDec('num',1);
if($re){
//模拟抢到了的客户,写入操作逻辑
file_put_contents('log.txt',$t."---ok\r\n",FILE_APPEND);
}else{
file_put_contents('log.txt',$t."--\r\n",FILE_APPEND);
}
}
用ab模拟测试, ab -r -n 1000 -c 500 http://192.168.1.112/index.php/index/index/sqla 代码运行正常!
下面用redis测试
//首先redis中将库存加入队列,
public function dos()
{
$redis = new \Redis();
$redis->connect('127.0.0.1', 6379);//serverip port
$count = 10;//redis中加入 列表 的数量 表示库存
$res=$redis->llen('goods_store');
echo $res;
for($i=0;$i<$count;$i++){
$redis->lpush('goods_store',1);
}
echo $redis->llen('goods_store');
}
//抢购环节 读取队列,队列没有了,表示抢购已经完成,没有库存了
public function sqlb(){
$redis = new \Redis();
$redis->connect('127.0.0.1', 6379);//serverip port
$count=$redis->lpop('goods_store');
echo $count;
if(!$count){
exit("over");
}
$re = db('qiang')->where('id',1)->setDec('num',1);//减库存
}