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操作。


/*************************************************************/
我通過你的問題,想象了一下你的環境。
可能是 有100個票。 10萬人搶。
你可以在服務器上做一個消息列隊。不論多少人搶票,都先放入消息列隊中。這樣,我們就把高並發,變成了統一的單線程。
這時候一切都好辦了。優點是緩解了MYSQL的瞬時壓力
但缺點是,如果1秒內1萬人點擊搶票。有可能會造成瞬時用戶訪問困難。(因為大家都在列隊)
如果你覺得慢了幾百毫秒不能忍,那你就需要換一個做法:
做一個競爭鎖,防止多個用戶同時獲取一張票。(票在MYSQL中)
在內存中存入一個標簽,來確定是否還有票。
當內存標簽說:沒有票了。 剩下的用戶一律歇菜。
這樣的優點是不論MYSQL,還是用戶,都很輕松。
缺點是,稍微有點小麻煩。 看你具體需求了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM