現在在電商行業裏,秒殺搶購活動已是商家經常使用促銷手段。可是庫存數量有限,而同時下單人數超過了庫存量,就會致使商品超賣甚至庫存變負數的問題。
又好比:搶購火車票、論壇搶樓、抽獎乃至爆紅微博評論等也會引起阻塞式高併發問題。若是不作任何措施可能在高瞬間形成服務器癱瘓,如何解決這個問題呢?
這裏提出我的認爲比較可行的幾個思路方法:
方案一:使用消息隊列來實現
能夠基於例如MemcacheQ等這樣的消息隊列,具體的實現方案這麼表述吧
好比有100張票可供用戶搶,那麼就能夠把這100張票放到緩存中,讀寫時不要加鎖。 當併發量大的時候,可能有500人左右搶票成功,這樣對於500後面的請求能夠直接轉到活動結束的靜態頁面。進去的500我的中有400我的是不可能得到 商品的。因此能夠根據進入隊列的前後順序只能前100我的購買成功。後面400我的就直接轉到活動結束頁面。固然進去500我的只是舉個例子,至於多少可 以本身調整。而活動結束頁面必定要用靜態頁面,不要用數據庫。這樣就減輕了數據庫的壓力。
方案二:當有多臺服務器時,能夠採用分流的形式實現
假設有m張票, 有n臺產品服務器接收請求,有x個請求路由服務器隨機轉發
直接給每臺產品服務器分配 m/n張票
每臺產品服務器內存作計數器,好比容許m/n*(1+0.1)我的進來。
當內存計數器已滿:
後面進的人, 直接跳到到轉到活動結束的靜態頁面,
通知路由服務器,不在路由到這臺服務器(這個值得商討)。
全部產品服務器進來的m/n*(1+0.1)我的再所有轉發到一臺付款服務器上,進入付款環節,看誰手快了,這時候人少,加鎖什麼的就簡單的。
方案3、若是是單服務器,能夠使用Memcache鎖來實現
product_key 爲票的key
product_lock_key 爲票鎖key
當product_key存在於memcached中時,全部用戶均可以進入下單流程。
當進入支付流程時,首先往memcached存放add(product_lock_key, 「1″),
若是返回成功,進入支付流程。
若是不成,則說明已經有人進入支付流程,則線程等待N秒,遞歸執行add操做。
方案4、藉助文件排他鎖
在處理下單請求的時候,用flock鎖定一個文件,若是鎖定失敗說明有其餘訂單正在處理,此時要麼等待要麼直接提示用戶"服務器繁忙"
本文要說的是第4種方案,大體代碼以下
阻塞(等待)模式:
<?php
$fp = fopen("lock.txt", "w+");
if(flock($fp,LOCK_EX))
{
//..處理訂單
flock($fp,LOCK_UN);
}
fclose($fp);
?>
非阻塞模式:
<?php
$fp = fopen("lock.txt", "w+");
if(flock($fp,LOCK_EX | LOCK_NB))
{
//..處理訂單
flock($fp,LOCK_UN);
}
else
{
echo "系統繁忙,請稍後再試";
}
fclose($fp);
?>php