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


}

12-31 00:36