PHP併發搶購解決方案

2022-07-12 18:36:08 字數 2610 閱讀 1457

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...