一个下单的小示例(上代码,没加事务的时候):
class IndexController extends Controller { public function index(){ $stock = M('stock'); $log = M('log'); $condition['id'] = 1; if($stock->where($condition)->getField('stock_left') > 0) { $stock->where($condition)->setDec("stock_left"); $data['op'] = 1; $log->add($data); } else { echo "已经没剩余了"; } } }
库存默认有100个:
日志表:
Apache ab工具并发一下:
ab -n 1200 -c 1200 -w http://localhost/queue/index.php >> D:/1.html
结果出并发问题(很自然的):
然后加了事务控制之后:
class IndexController extends Controller { public function index(){ $stock = M('stock'); $log = M('log'); $condition['id'] = 1; M()->startTrans(); if($stock->where($condition)->getField('stock_left') > 0) { $res1 = $stock->where($condition)->setDec("stock_left"); $data['op'] = 1; $res2 = $log->add($data); if($res1 !== false && $res2) { M()->commit(); } else { M()->rollback(); } } else { echo "已经没剩余了"; } } }
再测试并发一下:
ab -n 1200 -c 1200 -w http://localhost/queue/index.php >> D:/1.html
结果呢,输出的结果没问题(但是真的解决了并发问题吗?):
很多人说了用Redis队列来做,具体实施我还是有点不太清楚,请大家帮忙
DB->start_trans();
$res=DB->query("update tb_stock set stock_left=stock_left-1 where stock_left>0 and id=1");
if(!$res){
DB->rollback();
exit("库存不足");
}
DB->commit();