搶購、秒殺是現在很常見的一個應用場景,主要須要解決的問題有兩個:
1 高併發對數據庫產生的壓力
2 競爭狀態下如何解決庫存的正確減小("超賣"問題)
對於第一個問題,須要查看本站對mysql 具體優化的方案;這裏重點解決後者問題
減小超賣php
操做原理:
使用redis隊列,由於pop操做是原子的,即便有不少用戶同時到達,也是依次執行,推薦使用。mysql
一、在活動開始的前期,秒殺的腳本會將商品的庫存信息緩存到redis中
具體操做 (php)ajax
<?php
$store=1000; // 假設秒殺庫存設置1000個
$redis=new Redis();
$result=$redis->connect('127.0.0.1',6379); redis
$res=$redis->llen('goods_stock'); // 查看已經存在的庫存
var_dump($res);sql
if(intval($res)>=$store){
var_dump('庫存加滿了');
die();
}數據庫
$count=$store-$res;
for($i=0;$i<$count;$i++){
$redis->lpush('goods_stock',1); // 將庫存列表一次加入redis的列表
}緩存
$stock = $redis->llen('goods_stock');
var_dump(' 庫存補充到 1000 ');
?>併發
二、模擬搶購操做高併發
<?php優化
$redis=new Redis();
$result=$redis->connect('127.0.0.1',6379);
$peple = 1009; // 假設有 1009 個用戶來搶商品
for($i=0;$i<$peple;$i++){
$rrt = $redis->Lpop('goods_stock'); // Lpop 獲取 key 列表的頭元素並移除頭元素
if($rrt){
echo '搶到了 : '.$i.' ; res : '.$rrt; // 搶到了就進行下一步的下單操做
// TODO 進入正常的訂單流程
}else {
echo '售罄了 : '.$i; // 提示用戶沒有搶到
die();
}
echo '<br/>';
}
?>
上述只是簡單模擬高併發下的搶購,真實場景要比這複雜不少,不少注意的地方
如搶購頁面作成靜態的,經過ajax調用接口
再如上面的會致使一個用戶搶多個,思路:
在以上思路的基礎上添加一個 ‘排隊的隊列’,若是搶單的用戶已經在 ‘排隊的隊列’ 的隊列裏了 就提示用戶不能再搶了,並提示搶購失敗。