前言:
秒殺這個問題洽洁,一直以來都是經(jīng)典的面試題枫虏。但是秒殺也分大小报强。如果一個產(chǎn)品的用戶不超過5w灸姊,上來就問雙十一級別的秒殺。那就沒有意思了~秉溉,所以今天就簡單聊下一般條件下的秒殺的思路力惯。方法只有兩個,一個是裝載秒殺商品召嘶。一個就是模擬用戶進(jìn)場秒殺父晶。
工具介紹
首先環(huán)境就比較簡單
- Apache
- PHP 7.3
- redis
框架我選擇的ThinkPHP5.1 不過這次我主要還是選擇貼近原生的寫法
選擇apache的原因很簡單。自帶壓力測試工具ab弄跌。符合我們的需要甲喝。雖然我們知道nginx來做web服務(wù)器性能更好。
php7.* 這個不用多介紹了PHP 7 和 PHP 5的性能不是一個世界的
redis 雖然可以實(shí)現(xiàn)秒殺的方式有很多铛只。redis算是非常常見的緩存和中間件工具了埠胖。在性能和上手難度上都是很不錯的選擇
一.裝載秒殺商品
我們先假設(shè)我們有300個人來搶30件商品。那么我們就在我們的商品庫里面裝載30件不同id的商品
秒殺商品一般都是定時添加的淳玩。所以我們需要一個定時任務(wù)控制器用cli模式執(zhí)行
class Crontab
{
public function addGoods()
{
//設(shè)定商品數(shù)量
$count=30;
$listKey="2019_04_15_goods_list";
//創(chuàng)建連接redis對象
$redis = new \Redis();
$redis->connect('127.0.0.1', 6379);
for ($i=1;$i<=$count;$i++){
//將商品id push到列表中
$redis->rPush($listKey,$i);
}
}
}
然后當(dāng)我們需要裝載商品的時候我們使用php命令去執(zhí)行下我們的方法
php /項(xiàng)目地址/public/index.php index/crontab/addgoods
用redis客戶端查看下商品id是否放入成功
二.秒殺商品
秒殺商品其實(shí)就是一個將集合中的商品id取出和用戶id綁定的過程直撤。只是這個過程進(jìn)行的非常的快。那么我們將秒殺分為兩步蜕着,如果秒殺成功谋竖,則記錄下用戶id和商品id 也就是所謂的秒殺訂單。如果秒殺失敗承匣,我們則簡單的記錄一個秒殺失敗的人數(shù)蓖乘。來確定這次秒殺有多少有效用戶參與。
public function kill()
{
//假裝是用戶的唯一標(biāo)識
$uuid=md5(uniqid('user').time());
//創(chuàng)建連接redis對象
$redis = new \Redis();
$redis->connect('127.0.0.1', 6379);
$listKey="2019_04_15_goods_list";
$orderKey="2019_04_15_buy_order";
$failUserNum="2019_04_15_fail_user_num";
if ($goodsId=$redis->lPop($listKey)) {
//秒殺成功
//將幸運(yùn)用戶存在集合中
$redis->hSet($orderKey,$goodsId,$uuid);
}else{
//秒殺失敗
//將失敗用戶計數(shù)
$redis->incr($failUserNum);
}
echo "SUCCESS";
}
壓力測試模擬秒殺
剛剛有提到會使用apache自帶的ab做測試
小試牛刀 300并發(fā) 3000訪問量
ab -c 300 -n 3000 http://shop.example.com/index.php/index/index/kill
啥也不說就是干
雖說還是比較慢韧骗,但是3000次請求嘉抒,是全部命中沒有死掉的用戶。加上我本身docker性能沒給到最大袍暴。加上只有單機(jī)節(jié)點(diǎn)众眨。我對這個成績還是比較滿意的
下面來看看搶到商品的幸運(yùn)用戶
[root@2f7621a62356 bin]# redis-cli
127.0.0.1:6379> HGETALL 2019_04_15_buy_order
再看看秒殺失敗的用戶數(shù)量
這時候的商品list已經(jīng)空空如也了握牧。
好了,今天簡單做個秒殺娩梨,就介紹到這里。有時候思路比實(shí)現(xiàn)的方法更重要览徒。今天我所介紹的主要是一個思路和redis的用法狈定,現(xiàn)實(shí)中的秒殺肯定還有很多復(fù)雜的邏輯。我也是簡單介紹下习蓬。如果有什么不對的地方歡迎大神指點(diǎn)纽什。感謝
以上