下面测试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);//减库存
}
|