天天看點

PHP解決搶購、秒殺、搶樓、抽獎等阻塞式高并發庫存防控超量的思路方法PHP解決搶購、秒殺、搶樓、抽獎等阻塞式高并發庫存防控超量的思路方法

如今在電商行業裡,秒殺搶購活動已經是商家常用促銷手段。但是庫存數量有限,而同時下單人數超過了庫存量,就會導緻商品超賣甚至庫存變負數的問題。

又比如:搶購火車票、論壇搶樓、抽獎乃至爆紅微網誌評論等也會引發阻塞式高并發問題。如果不做任何措施可能在高瞬間造成伺服器癱瘓,如何解決這個問題呢?

這裡提出個人認為比較可行的幾個思路方法:方案一:使用消息隊列來實作

可以基于例如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)個人再全部轉發到一台付款伺服器上,進入付款環節,看誰手快了,這時候人少,加鎖什麼的就簡單的。

方案三、如果是單伺服器,可以使用Memcache鎖來實作

product_key 為票的key

product_lock_key 為票鎖key

當product_key存在于memcached中時,所有使用者都可以進入下單流程。

當進入支付流程時,首先往memcached存放add(product_lock_key, “1″),

如果傳回成功,進入支付流程。

如果不成,則說明已經有人進入支付流程,則線程等待N秒,遞歸執行add操作。

方案四、借助檔案排他鎖

在處理下單請求的時候,用flock鎖定一個檔案,如果鎖定失敗說明有其他訂單正在處理,此時要麼等待要麼直接提示使用者"伺服器繁忙"

本文要說的是第4種方案,大緻代碼如下

阻塞(等待)模式:

<?php

$fp = fopen("lock.txt", "w+");

if(flock($fp,LOCK_EX))

{

//..處理訂單

flock($fp,LOCK_UN);

}

fclose($fp);

?>

非阻塞模式:

if(flock($fp,LOCK_EX | LOCK_NB))

else

echo "系統繁忙,請稍後再試";