mysql儲存引擎使用innodb
開始事務,查詢商品庫存並加上共享鎖
判斷庫存是否足夠,進行商品/訂單/使用者等操作
提交事務,完成下單搶購
// 關閉自動提交
$this->db_conn->autocommit(false);//開啟事務
// //獲取商品庫存
$query_sql = 'select stock from goods where id ='.$goods_id .' lock in share mode'; //加mysql共享鎖[提交前不允許其他事務修改]
$stock = $this->query($query_sql);
if ($stock < $num)
//減庫存
$sql1 = 'update goods set stock = stock-'.$num.' where id='.$goods_id;
if (!$this->db_conn->query($sql1))
//建立訂單
$order_sn = date('ymdhis') . rand(1000,9999);
$sql2 = 'insert into `order` (order_sn,goods_id,goods_num,user_id) values ("'.$order_sn.'",'.$goods_id.','.$num.','.$user_id.')';
if (!$this->db_conn->query($sql2))
//提交事務
$this->db_conn->commit();
return true;
邏輯步驟
以商品id生成key,redis獲取庫存,開啟redis監控key和redis事務
開啟資料庫事務,減去庫存,建立訂單
$redis->exec();
redis執行,失敗資料庫rollback
;成功資料庫commit
;
**參考
//連線redis
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->auth('zylwan@redis123'); //密碼驗證
if (!$redis)
$redis->select(9);//選擇資料庫9
$stock_key = 'goods_id_stock_'.$goods_id; //商品庫存key
$stock = $redis->get($stock_key);
//監控key
$redis->watch($stock_key); //監控下單過程中key是否被修改
//開啟事務
$redis->multi();
if ($stock === false)
if ($stock < $num)
$redis->decr($stock_key);//redis減庫存
// 關閉mysql自動提交
$this->db_conn->autocommit(false);//開啟sql事務
$sql1 = 'update goods set stock = stock-'.$num.' where id='.$goods_id; //減mysql庫存
if (!$this->db_conn->query($sql1))
//開單
$order_sn = date('ymdhis') . rand(1000,9999);
$sql2 = 'insert into `order` (order_sn,goods_id,goods_num,user_id) values ("'.$order_sn.'",'.$goods_id.','.$num.','.$user_id.')';
if (!$this->db_conn->query($sql2))
$res = $redis->exec(); //執行redis事務
if ($res === false)
// 都成功執行,提交事務
$this->db_conn->commit();
return true;
邏輯步驟
搶購前將商品庫存放到佇列list中[庫存佇列] (庫存=佇列長度)
搶購開始,將使用者id放到hash佇列中[排隊hash佇列],已存在:跳過.不存在:繼續
減庫存操作lpop(list)
:
**參考
$user_id = 1;
$wait_key = "user_wait";//使用者搶購請求hash佇列
$user_key = "user";//使用者搶購成功list佇列
$stock_key = "goods_stock";//商品庫存佇列[在搶購開始前生成]
$result =$redis->hset($wait_key, $user_id, $user_id); //搶購使用者排隊,user_id去重
if ($result) else
} else
php 高併發解決方案(用於搶購)
最近在做乙個 專案,遇到個問題,就是在搶購 秒殺 等活動時,庫存數量有限,但是同時下單人數超過了庫存數量,就會導致商品超售問題。那麼我們怎麼來解決這個問題呢,我的思路如下 sql1 查詢商品庫存 if 庫存數量 0 當沒有併發時,上面的流程看起來是如此完美,假設同時兩個人下單,而庫存只有1個了,在s...
php併發解決方案
事務不能解決併發,只能保證在乙個事務內所有操作的一致性 常見的併發處理如下 1.悲觀鎖 為什麼叫悲觀鎖?預設每次的執行都會發生併發 表必須是innodb型別,必須在事務中執行,加上for update 查詢的表id 10資料是,這條資料就被鎖定了,第乙個人獲得鎖,後面的人只能等待第乙個人完成事務提交...
php高併發解決方案
最近在做乙個 專案,遇到個問題,就是在搶購 秒殺 等活動時,庫存數量有限,但是同時下單人數超過了庫存數量,就會導致商品超售問題。那麼我們怎麼來解決這個問題呢,我的思路如下 sql1 查詢商品庫存 if 庫存數量 0 當沒有併發時,上面的流程看起來是如此完美,假設同時兩個人下單,而庫存只有1個了,在s...