如果你家店裡某商品庫存只有100件,現在店慶活動5折優惠大酬賓,假如現在有200個人瘋狂湧入你家店裡,為了避免發生瘋搶和***件發生,店長您採取了排隊限購的辦法,1人限購1件,排隊先到先買,賣完為止。
這個是實體店我們會看到的場景,100件商品,1人1件,最後200人中只有100人能買到商品,剩下100人只能空手而歸。如果您開了家**,同樣你開起了秒殺的活動,可能同時會有1000人通過不同的終端訪問你的商品秒殺活動頁面,你的商品可以會在瞬間秒殺完畢,庫存清零。可是如果**秒殺活動程式設計出問題,會導致秒殺庫存超賣的現象,比如100件庫存,實際訂單有120件,原因就處在併發同時程式處理的問題上。
其實我們也可以採取排隊限購的辦法解決**秒殺活動商品超賣的問題。今天我們給大家講解採用php+redis+mysql解決商品秒殺活動中超賣問題。
把商品庫存數量加到redis佇列的num裡,下單的時候通過rpop從佇列中每次取1件商品,當num為0時,停止下單。
下面我們來看具體實現過程。
我們一共準備3張表,分別是:商品表、訂單表、日誌表。
create table `hw_goods` (
`id` int(11) not null auto_increment,
`name` varchar(128) default null comment '商品名稱',
`price` decimal(10,2) default null comment '商品**',
`pic` varchar(128) default null comment '商品',
`inventory` int(11) default null comment '庫存',
`created_at` datetime default null,
`updated_at` datetime default null,
primary key (`id`)
) engine=innodb auto_increment=2 default charset=utf8mb4;
-- ----------------------------
-- records of hw_goods
-- ----------------------------
create table `hw_order` (
`id` int(11) not null auto_increment,
`order_sn` varchar(32) default null comment '訂單號',
`user_id` int(11) default null comment '購買者id',
`status` tinyint(1) default '0' comment '訂單狀態1-已下單,2-已處理,3-已發貨,4-已收貨,5-訂單完成',
`goods_id` int(11) default '0' comment '商品id',
`o_num` int(11) default null comment '購買數量',
`price` int(10) default null comment '**,分',
`created_at` datetime default null,
`updated_at` datetime default null,
primary key (`id`)
) engine=innodb default charset=utf8mb4;
create table `hw_order_log` (
`id` int(11) not null auto_increment,
`status` int(11) default '0',
`msg` text,
`created_at` datetime default null,
primary key (`id`)
) engine=innodb default charset=utf8mb4;
for($i=1; $i <= 100; $i++)
執行完成後,我們可以看到redis佇列。
我們建立下單檔案order.php
首先是連線redis和mysql的**。
class order
return self::$redis;
}public static function mysql()
catch (pdoexception $e)
return self::$pdo;}}
接著就是搶購下單。我們從商品可以中取出商品資訊,然後從redis佇列num中rpop出列乙個商品數,接著馬上處理商品購買的過程。
// 搶購下單
public function goodsorder()
else
}
上述**中,如果redis佇列數量變成0了,就是沒有庫存了,這個時候不做訂單處理了,如果不是0就要更新庫存,生成訂單。
// 下單更新庫存
public function doorder($goods, $goodsnum)
$db = self::mysql();
try catch (exception $e)
}
在下單過程中,我們採用了mysql的事物機制,每次當訂單表中寫入訂單資料並且商品表扣除庫存-1成功,才算下單完成。
最後附上生產訂單號的**,以及日誌記錄**。
// 生成訂單號
public function orderno()
// 儲存日誌
public function log($status, $msg)
呼叫下單**:
$order = new order();
$order->goodsorder();
併發測試
我們apache的ab測試,ab是apachebench命令的縮寫,是apache自帶的壓力測試工具,假如你安裝了apache軟體後,在他的bin目錄下可以找到ab這個程式。
保證你的order.php在你的站點能訪問到,然後啟動ab測試,輸入以下命令:
ab -n 1000 -c 200 http://localhost/order.php
(-n發出1000個請求,-c模擬200併發,請求數要大於或等於併發數。相當1000人同時訪問,後面是測試url )。
執行結果如圖:
驗證結果
分別檢視商品表hw_goods,檢驗庫存欄位inventory是否由100變成0了。
檢視訂單表hw_order,查詢該商品的訂單總數是否為100。
檢視日誌表hw_order_log,查詢狀態status為1的訂單日誌記錄是否是100條,其餘的狀態均為0。
經驗證,庫存為0,訂單總數為100,並沒有出現超賣的現象。
PHP Redis秒殺搶購
string型別 apache併發請求 c 客戶端 n請求數量 ab.exe c700 n6000 192.168 88.151 82 檔名.php redis new redis redis connect 127.0.0.1 6379 對某乙個鍵加鎖 redis watch sales redi...
04載入秒殺商品實現
當前已經完成了秒殺時間段選單的顯示,那麼當使用者在切換不同的時間段的時候,需要按照使用者所選擇的時間去顯示相對應時間段下的秒殺商品 3.4.1 秒殺服務 查詢秒殺商品列表 restcontroller seckillgoods public class seckillgoodscontroller ...
組合商品秒殺
一.組合商品特點 支援多商品的選擇 多個商品的庫存 限購數量 驗證和處理的邏輯更多 其中一種庫存不足都要異常失敗 二.萬次秒殺 增加驗證邏輯,完成基本功能就可以 同樣不需要太多考慮優化方面 單機,mysql資料庫就可以支援 三.百萬次秒殺 1期組合商品秒殺相當也進行2 3期單商品秒殺同樣規模的壓力 ...