PHP Redis實現商品秒殺程式

2021-10-21 01:42:40 字數 3673 閱讀 3270

如果你家店裡某商品庫存只有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期單商品秒殺同樣規模的壓力 ...