首頁 後端開發 php教程 分享php秒殺功能實現的思路

分享php秒殺功能實現的思路

Sep 29, 2020 am 11:43 AM
php

分享php秒殺功能實現的思路

推薦:《PHP影片教學》 

一、秒殺業務為什麼難做

1)im系統,例如qq或微博,每個人都讀自己的資料(好友列表、群列表、個人資訊);

2)微博系統,每個人讀你關注的人的數據,一個人讀多個人的數據

#3)秒殺系統,庫存只有一份,所有人會在集中的時間讀取和寫這些數據,多個人讀一個數據

例如:小米手機每週二的秒殺,可能手機只有1萬部,但瞬時進入的流量可能是幾百幾千萬。

又例如:12306搶票,票是有限的,庫存一份,瞬時流量非常多,都讀相同的庫存。 讀寫衝突,鎖非常嚴重,這是秒殺業務困難的地方。那我們要怎麼優化秒殺業務的架構呢?

二、最佳化方向

最佳化方向有兩個(今天就講這兩個點):

(1)將請求盡量攔截在系統上游(不要讓鎖定衝突落到資料庫上去)。傳統秒殺系統之所以掛,請求都壓倒了後端資料層,資料讀寫鎖定衝突嚴重,並發高回應慢,幾乎所有請求都超時,流量雖大,下單成功的有效流量甚小。以12306為例,一班火車其實只有2000張票,200w個人來買,基本上沒有人能買成功,請求有效率為0。

(2)充分利用快取,秒殺買票,這是一個典型的讀多些少的應用場景,大部分請求是車次查詢,票查詢,下單和支付才是寫請求。一班火車其實只有2000張票,200w個人來買,最多2000個人下單成功,其他人都是查詢庫存,寫比例只有0.1%,讀比例佔99.9%,非常適合使用緩存來優化。好,後續講講怎麼個「將請求盡量攔截在系統上游」法,以及怎麼個「快取」法,講講細節。

三、常見秒殺架構

常見的網站架構基本上是這樣的(絕對不畫忽悠類別的架構圖)


(1)瀏覽器端,最上層,會執行到一些JS程式碼

(2)服務端,這一層會存取後端數據,拼html頁面回傳給瀏覽器

(3)服務層(web伺服器),向上游屏蔽底層資料細節,提供資料存取

(4)資料層,最終的庫存是存在這裡的,mysql是一個典型(當然還有會緩存)

這個圖雖然簡單,但能形象的說明大流量高並發的秒殺業務架構,大家要記得這張圖。

後面要細解析各層級怎麼優化。

四、各層次優化細節

第一層,客戶端怎麼優化(瀏覽器層,APP層)

問大家一個問題,大家都玩過微信的搖一搖搶紅包對吧,每次搖一搖,就會往後端發送請求麼?回顧我們下單搶票的場景,點擊了“查詢”按鈕之後,系統那個卡呀,進度條漲的慢呀,作為用戶,我會不自覺的再去點擊“查詢”,對麼?繼續點,繼續點,點點點。 。 。有用麼?平白無故的增加了系統負載,一個用戶點5次,80%的請求是這麼多出來的,怎麼整?

(a)產品層面,使用者點選「查詢」或「購票」後,按鈕置灰,禁止使用者重複提交請求;

(b)JS層面,限制使用者在x秒之內只能提交一次請求

APP層面,可以做類似的事情,雖然你瘋狂的在搖微信,其實x秒才向後端發起一次請求。這就是所謂的“將請求盡量攔截在系統上游”,越上游越好,瀏覽器層,APP層就給攔住,這樣就能擋住80% 的請求,這種辦法只能攔住普通用戶(但99%的用戶是普通用戶)對於群組內的高階程式設計師是攔不住的。 firebug一抓包,http長啥樣都知道,js是萬萬攔不住程式設計師寫for循環,呼叫http介面的,這部分請求怎麼處理?

第二層,服務端層面的請求攔截

怎麼攔截? 怎麼防止程式設計師寫for循環呼叫,有去重依據麼? ip? cookie-id? …想複雜了,這類業務都需要登錄,用uid即可。在服務端層面,對uid進行請求計數和去重,甚至不需要統一儲存計數,直接服務端記憶體儲存(這樣計數會不准,但最簡單)。一個uid,5秒只準透過1個請求,這樣又能攔住99%的for循環請求。

5s只透過一個請求,其餘的請求怎麼辦?緩存,頁面緩存,同一個uid,限制訪問頻度,做頁面緩存,x秒內到達服務端的請求,均返回同一頁。同一個item的查詢,例如車次,做頁面緩存,x秒內到達服務端的請求,均返回同一頁。如此限流,既能保證用戶有良好的用戶體驗(沒有返回404)又能保證系統的健壯性(利用頁面緩存,把請求攔截在服務端了) 。

頁面快取不一定要保證所有服務端傳回一致的頁面,直接放在每個網站的記憶體也是可以的。優點是簡單,壞處是http請求落到不同的服務端,回傳的車票資料可能不一樣,這是服務端的請求攔截與快取優化。

好,這個方式攔住了寫for循環發http請求的程式設計師,有些高階程式設計師(駭客)控制了10w個肉雞,手裡有10w個uid,同時發請求(先不考慮實名制的問題,小米搶手機不需要實名制),這下怎麼辦,服務端按照uid限流攔不住了。

第三層 服務層來攔截(反正就是不要讓請求落到資料庫上去)

服務層怎麼攔截?大哥,我是服務層,我清楚的知道小米只有1萬支手機,我清楚的知道一列火車只有2000張車票,我透10w個請求去數據庫有什麼意義呢?沒錯,請求隊列!

對於寫入請求,做請求隊列,每次只透有限的寫入請求去資料層(下訂單,支付這樣的寫業務)

1w部手機,只透1w個下單請求去db

3k張火車票,只透3k個下單請求去db

如果均成功再放下一批,如果庫存不夠則隊列裡的寫請求全部返回「已售完」。

對於讀取請求,怎麼優化? cache抗,不管是memcached還是redis,單機抗個每秒10w應該都是沒什麼問題的。如此限流,只有非常少的寫入請求,和非常少的讀取快取mis的請求會透到資料層去,又有99.9%的請求被攔住了。

當然,還有業務規則上的一些最佳化。回想12306所做的,分時分段售票,原來統一10點賣票,現在8點,8點半,9點,...每隔半小時放出一批:將流量攤勻。

其次,資料粒度的最佳化:你去購票,對於餘票查詢這個業務,票剩了58張,還是26張,你真的關注麼,其實我們只關心有票和無票?流量大的時候,做一個粗粒度的「有票」「無票」快取即可。

第三,一些業務邏輯的非同步:例如下單業務與 支付業務的分離。這些最佳化都是結合 業務 來的,我之前分享過一個觀點「一切脫離業務的架構設計都是耍流氓」架構的最佳化也要針對業務。

好了,最後是資料庫層

瀏覽器攔截了80%,服務端攔截了99.9%並做了頁面緩存,服務層又做了寫請求佇列與資料緩存,每次透到資料庫層的請求都是可控的。 db基本上就沒什麼壓力了,閒庭信步,單機也能扛得住,還是那句話,庫存是有限的,小米的產能有限,透這麼多請求來數據庫沒有意義。

全部透到資料庫,100w個下單,0個成功,請求有效率0%。透3k個到數據,全部成功,請求有效率100%。

五、總結

上文應該描述的非常清楚了,沒什麼總結了,對於秒殺系統,再次重複下我個人經驗的兩個架構優化思路:

(1)盡量將請求攔截在系統上游(越上游越好);

(2)讀多寫少的常用多使用快取(快取抗讀壓力);

瀏覽器與APP:做限速

服務端:依照uid做限速,做頁面快取

服務層(網頁伺服器):依照業務做寫入要求佇列控制流量,做資料快取

資料層:閒庭訊號步驟

並且:結合業務做最佳化

六、Q&A

問題1、按你的架構,其實壓力最大的反而是服務端,假設真實有效的請求數有1000萬,不太可能限制請求連接數吧,那麼這部分的壓力怎麼處理?

答:每秒鐘的並發可能沒有1kw,假設有1kw,解決方案2個:

(1)服務層(web伺服器)是可以透過加機器擴容的,最不濟1k台機器來嗆。

(2)如果機器不夠,拋棄請求,拋棄50%(50%直接回傳稍後再試),原則是要保護系統,不能讓所有使用者都失敗。

問題2、「控制了10w個肉雞,手上有10w個uid,同時發請求」 這個問題怎麼解決哈?

答:上面說了,服務層(web伺服器)寫入請求佇列控制

問題3:限制存取頻次的緩存,是否也可以用來搜尋?例如A用戶搜尋了“手機”,B用戶搜尋“手機”,優先使用A搜尋後產生的快取頁面?

答:這個是可以的,這個方法也常用在「動態」營運活動頁,例如短時間推送4kw用戶app-push營運活動,做頁面快取。

問題4:如果佇列處理失敗,該如何處理?肉雞把隊列被撐爆了怎麼辦?

答案:處理失敗回傳下單失敗,讓使用者再試一次。隊列成本很低,爆了很難吧。在最壞的情況下,快取了若干請求之後,後續請求都直接回傳「無票」(佇列裡已經有100w請求了,都等著,再接受請求也沒有意義了)

問題5 :服務端過濾的話,是把uid請求數單獨儲存到各個網站的記憶體中麼?如果是這樣的話,怎麼處理多台伺服器叢集經過負載平衡器將相同使用者的回應分散到不同伺服器的情況呢?還是說將服務端的過濾放到負載平衡前?

答:可以放在內存,這樣的話看似一台伺服器限制了5s一個請求,全局來說(假設有10台機器),其實是限制了5s 10個請求,解決辦法:

1)加大限制(這是建議的方案,最簡單)

2)在nginx層做7層均衡,讓一個uid的請求盡量落到同一個機器上

問題6:服務層(網頁伺服器)過濾的話,佇列是服務層(網頁伺服器)統一的一個佇列?還是每個提供服務的伺服器各一個佇列?如果是統一的一個佇列的話,需不需要在各伺服器提交的請求入佇列前進行鎖定控制?

答:可以不用統一一個佇列,這樣的話每個服務透過更少量的請求(總票數/服務個數),這樣簡單。統一一個隊列又複雜了。

問題7:秒殺後的支付完成,以及未支付取消佔位,如何對剩餘庫存做及時的控制更新?

答案:資料庫裡一個狀態,未支付。如果超過時間,例如45分鐘,庫存會重新會恢復(大家熟知的「回倉」),給我們搶票的啟示是,開動秒殺後,45分鐘之後再試試看,說不定又有票喲~

問題8:不同的使用者瀏覽同一個商品 落在不同的快取實例顯示的庫存完全不一樣 請問老師怎麼做快取資料一致或是允許髒讀?

答:目前的架構設計,請求落在不同的網站上,資料可能不一致(頁面快取不一樣),這個業務場景能接受。但資料庫層面真實資料是沒問題的。

問題9:就算處於業務把優化考慮「3k張火車票,只透3k個下單請求去db」那這3K個訂單就不會發生擁堵了嗎?

答:(1)資料庫抗3k個寫請求還是ok的;(2)可以資料拆分;(3)如果3k扛不住,服務層(web伺服器)可以控制透過去的並發數量,根據壓測情況來吧,3k只是舉例;

問題10;如果在服務端或服務層(web伺服器)處理後台失敗的話,需不需要考慮對這批次失敗的請求做重播?還是就直接丟棄?

答:別重播了,回傳使用者查詢失敗或下單失敗吧,架構設計原則之一是「fail fast」。

問題11.對於大型系統的秒殺,例如12306,同時進行的秒殺活動很多,如何分流?

答案:垂直拆分

問題12、額外又想到一個問題。這套流程做成同步還是非同步的?如果是同步的話,應該還存在會有回應回饋慢的情況。但如果是異步的話,如何控制能夠將回應結果傳回正確的請求方?

答:使用者層面肯定是同步的(使用者的http請求是夯住的),服務層(web伺服器)面可以同步可以非同步。

問題13、秒殺群問題:減庫存是在那個階段減呢?如果是下單鎖庫存的話,大量惡意用戶下單鎖庫存而不支付如何處理呢?

答:資料庫層面寫請求量很低,還好,下單不支付,等時間過完再“回倉”,之前提過了。

技巧:值的我們注意的地方

1、脫離原始網站部署(秒殺功能用的伺服器和商城伺服器不要放在同一個伺服器,防止秒殺崩咯,商城也不能訪問...)

2、多監控、注意監控、找個人盯著看

秒殺的關鍵點:

1、高可用:雙活

2、高並發:負載平衡、安全過濾

設計想法:

1、靜態頁面:cdn(使用各大廠商現成的)、網址隱藏、頁面壓縮、快取機制

2、動態頁面:排隊、非同步、資格搶購

其他建議:

##1、百度的建議:opcode快取、cdn 、更大的伺服器實例

2、阿里的建議:雲端監控、雲端盾牌、ecs、oss、rds、cdn

cdn的使用思路:

##1、靜態資源(圖片、js、css等)上傳到cdn

2、缺點:但要注意,更新時cdn更新不及時,這時就要推了

#1環境、形式:

1、使用者:超大量、正常/壞人(cdn加速也是一種分流,因為他就近訪問cdn的節點)

2、地理:全國各地(延遲1、2s也不行,因為延遲1s可能秒殺就結束了,需要cdn讓用戶就近選擇節點)

3、業務流程:前台商品展示、登記。後台資料存取、資料處理

在秒殺前加個頁面,可以分流、推廣其他商品

##商品展示層架構

頁面的3個狀態:

1、商品展示:倒數計時頁

#2、秒殺進行中:點選進入秒殺頁面

3、秒殺活動結束:提示活動已結束

新想法:以時間線來思考問題

假設我們看見的就是秒殺進行中,往前推就是倒數計時,往後推就是結束了

下圖是從使用者的角度看問題:

## :

靜態資源,存到oss裡部署

#先刪除倒數頁面,馬上給秒殺頁面複製過來

然後用coretab定時執行這個腳本

#總結:

從倒數計時到搶購中:是用linux的定時任務和shell腳本來做

搶購中倒搶購結束:php來做,查表沒了就結束

用戶登錄層架構

#程式碼:

#$.cookie的封裝

資料存取層

 

程式碼:

 

第2層到第3層的時候要怎麼計算? ?

第2層發送資料到第3層網路傳輸dns解析等因素總共造成的延遲大概是多久,這樣就可以評估,需要配置伺服器的數量

#總結為2句話:

1、在關鍵點上不通過,直接回到上一層(使用者登記層)

2、在關鍵點通過,就會通知其他層

效驗:類似微軟序號的加密解密

佇列:使用redis的有序集合

上限:技術標誌位元

資料處理層

#

#

以上是分享php秒殺功能實現的思路的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1666
14
CakePHP 教程
1425
52
Laravel 教程
1325
25
PHP教程
1273
29
C# 教程
1252
24
PHP和Python:比較兩種流行的編程語言 PHP和Python:比較兩種流行的編程語言 Apr 14, 2025 am 12:13 AM

PHP和Python各有優勢,選擇依據項目需求。 1.PHP適合web開發,尤其快速開發和維護網站。 2.Python適用於數據科學、機器學習和人工智能,語法簡潔,適合初學者。

PHP:網絡開發的關鍵語言 PHP:網絡開發的關鍵語言 Apr 13, 2025 am 12:08 AM

PHP是一種廣泛應用於服務器端的腳本語言,特別適合web開發。 1.PHP可以嵌入HTML,處理HTTP請求和響應,支持多種數據庫。 2.PHP用於生成動態網頁內容,處理表單數據,訪問數據庫等,具有強大的社區支持和開源資源。 3.PHP是解釋型語言,執行過程包括詞法分析、語法分析、編譯和執行。 4.PHP可以與MySQL結合用於用戶註冊系統等高級應用。 5.調試PHP時,可使用error_reporting()和var_dump()等函數。 6.優化PHP代碼可通過緩存機制、優化數據庫查詢和使用內置函數。 7

PHP行動:現實世界中的示例和應用程序 PHP行動:現實世界中的示例和應用程序 Apr 14, 2025 am 12:19 AM

PHP在電子商務、內容管理系統和API開發中廣泛應用。 1)電子商務:用於購物車功能和支付處理。 2)內容管理系統:用於動態內容生成和用戶管理。 3)API開發:用於RESTfulAPI開發和API安全性。通過性能優化和最佳實踐,PHP應用的效率和可維護性得以提升。

PHP與Python:了解差異 PHP與Python:了解差異 Apr 11, 2025 am 12:15 AM

PHP和Python各有優勢,選擇應基於項目需求。 1.PHP適合web開發,語法簡單,執行效率高。 2.Python適用於數據科學和機器學習,語法簡潔,庫豐富。

PHP的持久相關性:它還活著嗎? PHP的持久相關性:它還活著嗎? Apr 14, 2025 am 12:12 AM

PHP仍然具有活力,其在現代編程領域中依然佔據重要地位。 1)PHP的簡單易學和強大社區支持使其在Web開發中廣泛應用;2)其靈活性和穩定性使其在處理Web表單、數據庫操作和文件處理等方面表現出色;3)PHP不斷進化和優化,適用於初學者和經驗豐富的開發者。

PHP和Python:代碼示例和比較 PHP和Python:代碼示例和比較 Apr 15, 2025 am 12:07 AM

PHP和Python各有優劣,選擇取決於項目需求和個人偏好。 1.PHP適合快速開發和維護大型Web應用。 2.Python在數據科學和機器學習領域佔據主導地位。

PHP與其他語言:比較 PHP與其他語言:比較 Apr 13, 2025 am 12:19 AM

PHP適合web開發,特別是在快速開發和處理動態內容方面表現出色,但不擅長數據科學和企業級應用。與Python相比,PHP在web開發中更具優勢,但在數據科學領域不如Python;與Java相比,PHP在企業級應用中表現較差,但在web開發中更靈活;與JavaScript相比,PHP在後端開發中更簡潔,但在前端開發中不如JavaScript。

PHP和Python:解釋了不同的範例 PHP和Python:解釋了不同的範例 Apr 18, 2025 am 12:26 AM

PHP主要是過程式編程,但也支持面向對象編程(OOP);Python支持多種範式,包括OOP、函數式和過程式編程。 PHP適合web開發,Python適用於多種應用,如數據分析和機器學習。

See all articles