第一种方法:使用mysql数据库的锁机制。在事务中使用 for update 语句,在事务处理完成之后释放这一条数据。
代码使用tp5的框架:
public function mysqlLock(){
$goods_id = 26545;
$sku_id = 26545;
$price = 300;
$user = '';
StoreOrderModel::startTrans();
$nums = StoreOrderModel::where(['id'=>1])->field('number')->lock(true)->find();
$nums = $nums['number'];
if($nums > 0){
$item['goods_id'] = $goods_id;
$item['sku_id'] = $sku_id;
$item['number'] = $nums;
$item['price'] = $price;
$item['user'] = $user;
$id = StoreModel::insertGetId($item);
if($id){
StoreOrderModel::where(['id'=>1])->setDec('number');
StoreOrderModel::commit();
}else{
StoreOrderModel::rollback();
}
}else{
echo "没有库存了";
}
}
第二种方法:redis 事务。
public function start_reids_tran(){
$goods_id = 26545;
$sku_id = 26545;
//$number = 1;
$price = 300;
$user = '';
$redis = ResRedisModel::getinstance();
$redis->watch('store');
$nums = intval($redis->get('store'));
if($nums > 0){
$item['goods_id'] = $goods_id;
$item['sku_id'] = $sku_id;
$item['number'] = $nums;
$item['price'] = $price;
$item['user'] = $user;
$redis->lPush('success', json_encode($item));
$redis->multi();
$redis->decr('store');
$replies = $redis->exec(); // 执行以上 redis 事务
if(!$replies){
echo "订单 {$nums} 回滚".PHP_EOL;
}
$redis->unwatch();
echo "抢购成功!".PHP_EOL;
}else{
echo "没有库存了";
}
}
- 26
- 27
- 28
第三种方法:redis 队列,预先把库存信息存入队列当中,抢购时判断队列的数量,然后出队。队列为空时库存为0。
public function eq_start(){
$redis = ResRedisModel::getinstance();
$nums = $redis->lSize('store');
$goods_id = 26545;
$sku_id = 26545;
$number = 1;
$price = 300;
$user = '';
if($nums > 0){
$user = $redis->rPop('store');
if($user){
$item['goods_id'] = $goods_id;
$item['sku_id'] = $sku_id;
$item['number'] = $number;
$item['price'] = $price;
$item['user'] = $user;
StoreModel::insertGetId($item);
echo '抢购成功!';
}else{
echo '抢购失败!';
}
}else{
echo '抢购失败!';
}
}
- 26
- 27
第四种:文件排他锁方式
public function file_star(){
$fp = fopen('D:/phpStudy/PHPTutorial/www/public/lock.txt', "r");
if(flock($fp, LOCK_EX)) { //排他型锁定 阻塞模式 , flock($fp,LOCK_EX | LOCK_NB) 非阻塞模式
$nums = StoreOrderModel::where(['id'=>1])->field('number')->find();
$nums = $nums['number'];
if($nums > 0){
$goods_id = 26545;
$sku_id = 26545;
$number = 1;
$price = 300;
$user = '213';
$item['goods_id'] = $goods_id;
$item['sku_id'] = $sku_id;
$item['number'] = $number;
$item['price'] = $price;
$item['user'] = $user;
StoreModel::insertGetId($item);
StoreOrderModel::where(['id'=>1])->setDec('number');
flock($fp, LOCK_UN); //释放锁定
echo '抢购成功!';
}else{
echo '没有库存了!';
}
}else{
echo '抢购失败!';
}
fclose($fp);
}
- 26
- 27
- 28
- 29
- 30
- 31
- 32