下面測試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);//減庫存
}