PHP处理库存超卖的几种处理方法???
2023-09-14 09:14:20 时间
第一种方法:使用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 "没有库存了";
}
}
第三种方法: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 '抢购失败!';
}
}
第四种:文件排他锁方式
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);
}
相关文章
- 如何遍历php数组时,同时取出array的下标和值
- PHP 的异常处理、错误处理:error_reporting,try-catch,trigger_error,set_error_handler,set_exception_handler,register_shutdown_function
- 【PHP面向对象(OOP)编程入门教程】19.抽象方法和抽象类(abstract)
- 【PHP面向对象(OOP)编程入门教程】16.__toString()方法
- php中n阶乘的实现方法
- php:PHP解析xml的4种方法
- PHP读取日志里数据方法理解
- php安装扩展的几种方法
- php提示undefined index的几种解决方法
- thinkphp6: 前后端分离:用jwt+middleware做用户登录验证(php 8.1.1 / thinkphp v6.0.10LTS )
- LZW算法PHP实现方法 lzw_decompress php
- phpExcel常用方法详解【附有php导出excel加超级链接】
- PHP反序列化详解(二)——PHP魔术方法与PHP反序列化漏洞
- [php-src] Php内核的有趣高频宏
- PHP获取用户访问IP地址的5种方法
- Atitit 业务流程执行引擎的实现 目录 1.1. 引擎实现语言java js php等1 1.2. 流程语言 xml sql js等 业务流程定义语言规范总结1 1.3. 实体方法定义2
- paip.编程语言方法重载实现的原理及python,php,js中实现方法重载