1. vc/mfc 進程消息隊列,線程消息隊列,和系統消息隊列,該如何處理
隊列消息和非隊列消息
從消息的發送途徑來看,消息可以分成2種:隊列消息和非隊列消息。消息隊列由可以分成系統消息隊列和線程消息隊列。系統消息隊列由Windows維護,線程消息隊列則由每個GUI線程自己進行維護,為避免給non-GUI現成創建消息隊列,所有線程產生時並沒有消息隊列,僅當線程第一次調用GDI函數數系統給線程創建一個消息隊列。隊列消息送到系統消息隊列,然後到線程消息隊列;非隊列消息直接送給目的窗口過程。
對於隊列消息,最常見的是滑鼠和鍵盤觸發的消息,例如WM_MOUSERMOVE,WM_CHAR等消息,還有一些其它的消息,例如:WM_PAINT、WM_TIMER和WM_QUIT。當滑鼠、鍵盤事件被觸發後,相應的滑鼠或鍵盤驅動程序就會把這些事件轉換成相應的消息,然後輸送到系統消息隊列,由Windows系統去進行處理。Windows系統則在適當的時機,從系統消息隊列中取出一個消息,根據前面我們所說的MSG消息結構確定消息是要被送往那個窗口,然後把取出的消息送往創建窗口的線程的相應隊列,下面的事情就該由線程消息隊列操心了,Windows開始忙自己的事情去了。線程看到自己的消息隊列中有消息,就從隊列中取出來,通過操作系統發送到合適的窗口過程去處理。
一般來講,系統總是將消息Post在消息隊列的末尾。這樣保證窗口以先進先出的順序接受消息。然而,WM_PAINT是一個例外,同一個窗口的多個 WM_PAINT被合並成一個 WM_PAINT 消息, 合並所有的無效區域到一個無效區域。合並WM_PAIN的目的是為了減少刷新窗口的次數。
非隊列消息將會繞過系統隊列和消息隊列,直接將消息發送到窗口過程,。系統發送非隊列消息通知窗口,系統發送消息通知窗口。 例如,當用戶激活一個窗口系統發送WM_ACTIVATE, WM_SETFOCUS, and WM_SETCURSOR。這些消息通知窗口它被激活了。非隊列消息也可以由當應用程序調用系統函數產生。例如,當程序調用SetWindowPos系統發送WM_WINDOWPOSCHANGED消息。一些函數也發送非隊列消息,例如下面我們要談到的函數。
消息的發送
了解了上面的這些基礎理論之後,我們就可以進行一下簡單的消息發送與接收。
把一個消息發送到窗口有3種方式:發送、寄送和廣播。
發送消息的函數有SendMessage、SendMessageCallback、SendNotifyMessage、SendMessageTimeout;寄送消息的函數主要有PostMessage、PostThreadMessage、PostQuitMessage;廣播消息的函數我知道的只有BroadcastSystemMessage、BroadcastSystemMessageEx。
SendMessage的原型如下:LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam),這個函數主要是向一個或多個窗口發送一條消息,一直等到消息被處理之後才會返回。不過需要注意的是,如果接收消息的窗口是同一個應用程序的一部分,那麼這個窗口的窗口函數就被作為一個子程序馬上被調用;如果接收消息的窗口是被另外的線程所創建的,那麼窗口系統就切換到相應的線程並且調用相應的窗口函數,這條消息不會被放進目標應用程序隊列中。函數的返回值是由接收消息的窗口的窗口函數返回,返回的值取決於被發送的消息。
PostMessage的原型如下:BOOL PostMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam),該函數把一條消息放置到創建hWnd窗口的線程的消息隊列中,該函數不等消息被處理就馬上將控制返回。需要注意的是,如果hWnd參數為HWND_BROADCAST,那麼,消息將被寄送給系統中的所有的重疊窗口和彈出窗口,但是子窗口不會收到該消息;如果hWnd參數為NULL,則該函數類似於將dwThreadID參數設置成當前線程的標志來調用PostThreadMEssage函數。
從上面的這2個具有代表性的函數,我們可以看出消息的發送方式和寄送方式的區別所在:被發送的消息是否會被立即處理,函數是否立即返回。被發送的消息會被立即處理,處理完畢後函數才會返回;被寄送的消息不會被立即處理,他被放到一個先進先出的隊列中,一直等到應用程序空線的時候才會被處理,不過函數放置消息後立即返回。
實際上,發送消息到一個窗口處理過程和直接調用窗口處理過程之間並沒有太大的區別,他們直接的唯一區別就在於你可以要求操作系統截獲所有被發送的消息,但是不能夠截獲對窗口處理過程的直接調用。
以寄送方式發送的消息通常是與用戶輸入事件相對應的,因為這些事件不是十分緊迫,可以進行緩慢的緩沖處理,例如滑鼠、鍵盤消息會被寄送,而按鈕等消息則會被發送。
廣播消息用得比較少,BroadcastSystemMessage函數原型如下:
long BroadcastSystemMessage(DWORD dwFlags,LPDWORD lpdwRecipients,UINT uiMessage,WPARAM wParam,LPARAM lParam);
該函數可以向指定的接收者發送一條消息,這些接收者可以是應用程序、可安裝的驅動程序、網路驅動程序、系統級別的設備驅動消息和他們的任意組合。需要注意的是,如果dwFlags參數是BSF_QUERY並且至少一個接收者返回了BROADCAST_QUERY_DENY,則返回值為0,如果沒有指定BSF_QUERY,則函數將消息發送給所有接收者,並且忽略其返回值。
窗口過程
窗口過程是一個用於處理所有發送到這個窗口的消息的函數。任何一個窗口類都有一個窗口過程。同一個類的窗口使用同樣的窗口過程來響應消息。 系統發送消息給窗口過程將消息數據作為參數傳遞給他,消息到來之後,按照消息類型排序進行處理,其中的參數則用來區分不同的消息,窗口過程使用參數產生合適行為。
一個窗口過程不經常忽略消息,如果他不處理,它會將消息傳回到執行默認的處理。窗口過程通過調用DefWindowProc來做這個處理。窗口過程必須return一個值作為它的消息處理結果。大多數窗口只處理小部分消息和將其他的通過DefWindowProc傳遞給系統做默認的處理。窗口過程被所有屬於同一個類的窗口共享,能為不同的窗口處理消息。下面我們來看一下具體的實例:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
TCHAR szHello[MAX_LOADSTRING];
LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
RECT rt;
GetClientRect(hWnd, &rt);
DrawText(hdc, szHello, strlen(szHello), &rt, DT_CENTER);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
消息分流器
通常的窗口過程是通過一個switch語句來實現的,這個事情很煩,有沒有更簡便的方法呢?有,那就是消息分流器,利用消息分流器,我們可以把switch語句分成更小的函數,每一個消息都對應一個小函數,這樣做的好處就是對消息更容易管理。
之所以被稱為消息分流器,就是因為它可以對任何消息進行分流。下面我們做一個函數就很清楚了:
void MsgCracker(HWND hWnd,int id,HWND hWndCtl,UINT codeNotify)
{
switch(id)
{
case ID_A:
if(codeNotify==EN_CHANGE)...
break;
case ID_B:
if(codeNotify==BN_CLICKED)...
break;
....
}
}
然後我們修改一下窗口過程:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
HANDLE_MSG(hWnd,WM_COMMAND,MsgCracker);
HANDLE_MSG(hWnd,WM_DESTROY,MsgCracker);
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
在WindowsX.h中定義了如下的HANDLE_MSG宏:
#define HANDLE_MSG(hwnd,msg,fn) \
switch(msg): return HANDLE_##msg((hwnd),(wParam),(lParam),(fn));
實際上,HANDLE_WM_XXXX都是宏,例如:HANDLE_MSG(hWnd,WM_COMMAND,MsgCracker);將被轉換成如下定義:
#define HANDLE_WM_COMMAND(hwnd,wParam,lParam,fn)\
((fn)((hwnd),(int)(LOWORD(wParam)),(HWND)(lParam),(UINT)HIWORD(wParam)),0L);
好了,事情到了這一步,應該一切都明朗了。
不過,我們發現在windowsx.h裡面還有一個宏:FORWARD_WM_XXXX,我們還是那WM_COMMAND為例,進行分析:
#define FORWARD_WM_COMMAND(hwnd, id, hwndCtl, codeNotify, fn) \
(void)(fn)((hwnd), WM_COMMAND, MAKEWPARAM((UINT)(id),(UINT)(codeNotify)), (LPARAM)(HWND)(hwndCtl))
所以實際上,FORWARD_WM_XXXX將消息參數進行了重新構造,生成了wParam && lParam,然後調用了我們定義的函數。
MFC消息的處理實現方式
初看MFC中的各種消息,以及在頭腦中根深蒂固的C++的影響,我們可能很自然的就會想到利用C++的三大特性之一:虛擬機制來實現消息的傳遞,但是經過分析,我們看到事情並不是想我們想像的那樣,在MFC中消息是通過一種所謂的消息映射機制來處理的。
為什麼呢?在潘愛民老師翻譯的《Visual C++技術內幕》(第4版)中給出了詳細的原因說明,我再簡要的說一遍。在CWnd類中大約有110個消息,還有其它的MFC的類呢,算起來消息太多了,在C++中對程序中用到的每一個派生類都要有一個vtable,每一個虛函數在vtable中都要佔用一個4位元組大小的入口地址,這樣一來,對於每個特定類型的窗口或控制項,應用程序都需要一個440KB大小的表來支持虛擬消息控制項函數。
如果說上面的窗口或控制項可以勉強實現的話,那麼對於菜單命令消息及按鈕命令消息呢?因為不同的應用程序有不同的菜單和按鈕,我們怎麼處理呢?在MFC庫的這種消息映射系統就避免了使用大的vtable,並且能夠在處理常規Windows消息的同時處理各種各樣的應用程序的命令消息。
說白了,MFC中的消息機制其實質是一張巨大的消息及其處理函數的一一對應表,然後加上分析處理這張表的應用框架內部的一些程序代碼.這樣就可以避免在SDK編程中用到的繁瑣的CASE語句。
MFC的消息映射的基類CCmdTarget
如果你想讓你的控制項能夠進行消息映射,就必須從CCmdTarget類中派生。CCmdTarget類是MFC處理命令消息的基礎、核心。MFC為該類設計了許多成員函數和一些成員數據,基本上是為了解決消息映射問題的,所有響應消息或事件的類都從它派生,例如:應用程序類、框架類、文檔類、視圖類和各種各樣的控制項類等等,還有很多。
不過這個類裡面有2個函數對消息映射非常重要,一個是靜態成員函數DispatchCmdMsg,另一個是虛函數OnCmdMsg。
DispatchCmdMsg專門供MFC內部使用,用來分發Windows消息。OnCmdMsg用來傳遞和發送消息、更新用戶界面對象的狀態。
CCmdTarget對OnCmdMsg的默認實現:在當前命令目標(this所指)的類和基類的消息映射數組里搜索指定命令消息的消息處理函數。
這里使用虛擬函數GetMessageMap得到命令目標類的消息映射入口數組_messageEntries,然後在數組里匹配命令消息ID相同、控制通知代碼也相同的消息映射條目。其中GetMessageMap是虛擬函數,所以可以確認當前命令目標的確切類。
如果找到了一個匹配的消息映射條目,則使用DispachCmdMsg調用這個處理函數;
如果沒有找到,則使用_GetBaseMessageMap得到基類的消息映射數組,查找,直到找到或搜尋了所有的基類(到CCmdTarget)為止;
如果最後沒有找到,則返回FASLE。
每個從CCmdTarget派生的命令目標類都可以覆蓋OnCmdMsg,利用它來確定是否可以處理某條命令,如果不能,就通過調用下一命令目標的OnCmdMsg,把該命令送給下一個命令目標處理。通常,派生類覆蓋OnCmdMsg時 ,要調用基類的被覆蓋的OnCmdMsg。
在MFC框架中,一些MFC命令目標類覆蓋了OnCmdMsg,如框架窗口類覆蓋了該函數,實現了MFC的標准命令消息發送路徑。必要的話,應用程序也可以覆蓋OnCmdMsg,改變一個或多個類中的發送規定,實現與標准框架發送規定不同的發送路徑。例如,在以下情況可以作這樣的處理:在要打斷發送順序的類中把命令傳給一個非MFC默認對象;在新的非默認對象中或在可能要傳出命令的命令目標中。
消息映射的內容
通過ClassWizard為我們生成的代碼,我們可以看到,消息映射基本上分為2大部分:
在頭文件(.h)中有一個宏DECLARE_MESSAGE_MAP(),他被放在了類的末尾,是一個public屬性的;與之對應的是在實現部分(.cpp)增加了一章消息映射表,內容如下:
BEGIN_MESSAGE_MAP(當前類, 當前類的基類)
file://{{AFX_MSG_MAP(CMainFrame)
消息的入口項
file://}}AFX_MSG_MAP
END_MESSAGE_MAP()
但是僅是這兩項還遠不足以完成一條消息,要是一個消息工作,必須有以下3個部分去協作:
1.在類的定義中加入相應的函數聲明;
2.在類的消息映射表中加入相應的消息映射入口項;
3.在類的實現中加入相應的函數體;
消息的添加
有了上面的這些只是作為基礎,我們接下來就做我們最熟悉、最常用的工作:添加消息。MFC消息的添加主要有2種方法:自動/手動,我們就以這2種方法為例,說一下如何添加消息。
1、利用Class Wizard實現自動添加
在菜單中選擇View-->Class Wizard,也可以用單擊滑鼠右鍵,選擇Class Wizard,同樣可以激活Class Wizard。選擇Message Map標簽,從Class name組合框中選取我們想要添加消息的類。在Object IDs列表框中,選取類的名稱。此時, Messages列表框顯示該類的大多數(若不是全部的話)可重載成員函數和窗口消息。類重載顯示在列表的上部,以實際虛構成員函數的大小寫字母來表示。其他為窗口消息,以大寫字母出現,描述了實際窗口所能響應的消息ID。選中我們向添加的消息,單擊Add Function按鈕,Class Wizard自動將該消息添加進來。
有時候,我們想要添加的消息本應該出現在Message列表中,可是就是找不到,怎麼辦?不要著急,我們可以利用Class Wizard上Class Info標簽以擴展消息列表。在該頁中,找到Message Filter組合框,通過它可以改變首頁中Messages列表框中的選項。這里,我們選擇Window,從而顯示所有的窗口消息,一把情況下,你想要添加的消息就可以在Message列表框中出現了,如果還沒有,那就接著往下看:)
2、手動地添加消息處理函數
如果在Messages列表框中仍然看不到我們想要的消息,那麼該消息可能是被系統忽略掉或者是你自己創建的,在這種情況下,就必須自己手工添加。根據我們前面所說的消息工作的3個部件,我們一一進行處理:
1) 在類的. h文件中添加處理函數的聲明,緊接在//}}AFX_MSG行之後加入聲明,注意:一定要以afx_msg開頭。
通常,添加處理函數聲明的最好的地方是源代碼中Class Wizard維護的表下面,但是在它標記其領域的{{}}括弧外面。這些括弧中的任何東西都將會被Class Wizard銷毀。
2) 接著,在用戶類的.cpp文件中找到//}}AFX_MSG_MAP行,緊接在它之後加入消息入口項。同樣,也是放在{ {} }的外面
3) 最後,在該文件中添加消息處理函數的實體。
2. 如何設計一個秒殺系統,小米秒殺系統設計
小米手機 4 採用了高通驍龍801手機處理器,內含四個Krait 400 2.5GHz 處理核心。運算速度提升14%,性能更強大。支回持4G網路答,下行峰值速率最高可達到132Mbps,上傳的速度可達31Mbps。
小米手機4 採用了高色彩飽和度夏普 / JDI 屏幕,達到95%NTSC色域,令色彩表現力更加豐富。還有全新升級的陽光屏,採用「像素級動態對比度調整」技術,在刺眼的陽光下,也可享受清晰的瀏覽體驗。
小米手機4 採用索尼 / 三星堆棧式圖像感測器,通過減少片上微透鏡與感光二極體的距離,使其更容易集合光線。支持硬體更豐富、噪點更少的照片。
小米手機4 內置紅外遙控功能,支持與紅外接受設備的傳輸協議,可以通過專門為這一功能定製的小米遙控器App,遙控家裡電視、空調等支持紅外協議的家用電器。
精心打磨的不銹鋼金屬邊框、鎂合金極輕構架成就了堅固的機身,超窄邊屏幕的精妙設計,宛如藝術品般的後蓋賦予了小米手機舒適的手感。
3. 如何實現「秒殺」系統
因為秒殺活動只是網站營銷的一個附加活動,這個活動具有時間短,並發訪問量大的特點,如果和網站原有應用部署在一起,必然會對現有業務造成沖擊,稍有不慎可能導致整個網站癱瘓。
2) 高並發情況以及資料庫的負載
用戶在秒殺開始前,通過不停的刷新瀏覽器頁面以保證不會錯過秒殺,這些請求如果按照一般的網站應用架構,訪問應用伺服器、連接資料庫,會對應用伺服器、資料庫伺服器造成極大的負載壓力。
3) 突然增加的網路和伺服器帶寬
假設商品頁面大小200K(主要是商品圖片大小),那麼需要的網路和伺服器帶寬是2G(200K×10,000),這些網路帶寬是因為秒殺活動新增的,超過網站平時使用的帶寬。
4) 直接下單
秒殺的游戲規則是到了秒殺時間才能開始對商品下單購買,在此時間點之前,只能瀏覽商品信息,不能下單。而下單頁面也是一個普通的URL,如果得到這個URL,不用等到秒殺開始就可以下單了。
5) 防止機器秒殺
防止網上的一些「秒殺器」
針對上面的5個問題,對應的策略如下:
1) 秒殺系統獨立部署
為了避免因為秒殺活動的高並發訪問而拖垮整個網站,使整個網站不必面對蜂擁而來的用戶訪問,將秒殺系統獨立部署,如果需要,還可以使用獨立的域名,以和網站完全隔離,即使秒殺系統崩潰了,也不會對網站造成任何影響。
2) 秒殺商品頁面靜態化
秒殺商品頁面重新設計,不使用網站原來的商品詳情頁面,頁面內容靜態化:商品描述,商品參數,成交記錄,用戶評價全部寫入一個靜態頁面,用戶請求不需要經過應用伺服器的業務邏輯處理,也不需要訪問資料庫。所以秒殺商品服務不需要部署動態的Web伺服器、資料庫伺服器。
3) 租借秒殺活動網路帶寬
對於因為秒殺新增的網路帶寬,必須和運營商重新購買或者租借。為了減輕網站伺服器的壓力,需要將秒殺商品頁面緩存在CDN,同樣需要和CDN服務商臨時租借新增的出口帶寬。
4) 動態生成隨機下單頁面URL
為了避免用戶直接訪問下單頁面URL,需要將該URL動態化,即使秒殺系統的開發者也無法在秒殺開始前訪問下單頁面的URL。辦法是在下單頁面URL加入由伺服器端生成的隨機數作為參數,在秒殺開始的時候才能得到。
5) 防止「秒殺器」感覺很難,
因為似乎總是有辦法可以跳過設置的「障礙」。真正做到防止,僅靠webserver怕是很難防範,一般的做法都是增加一些人為的「障礙」,比如:
注冊時有一定的門檻,像皮皮書屋一樣,通過輸入程序執行結果作為驗證 –à之前批量手工注冊
參加秒殺的積分或者等級策略 -à 掛太陽,就如同你當你為了升級QQ等級的時候一直掛著QQ一樣。
驗證碼,阻止自動化操作 -à 可以圖像識別
ip阻止 –à 但是ip可以偽造,可以代理
4. 如何設計一個秒殺系統
(純分析一波,如果有什麼方面沒考慮到,希望各位大咖見諒,並且給我提點哦~ 可以繼續完善) 首先, 在購票方面, 最主要的一點是要防止黃牛囤積大量票, 第二步在防止黃牛用自己的賬號隨便買票, 第三步才考慮完全杜絕黃牛為其他人代購票。 首先說圖片驗證碼, 圖片驗證碼的作用就是用在最後一步的, 至於為什麼不是用於防止黃牛大量囤積或者用於防止黃牛用自己的賬號買票, 因為圖片驗證碼總有一個概率通過,根據現在的驗證碼規則, 在8個圖中選擇1~3個圖,那麼隨機選一個選中的概率就是1/(8C1+8C2+8C3)=1/92≈1.086% (應用一下中學排列組合知識,C 表示組合數),也就是說, 黃牛買100次票就會有一次搶到票, 這對於一般用戶來說這是沒用的, 一般的用戶就算有這個軟體, 100次才有一次那需要的次數也太多了,但對於大量囤積票來說,這就足夠了,一個機器人100趟車只能搶到一次,開幾十幾百個機器人搶就是了,有錢想囤積多少都可以。而防止黃牛拿自己的賬號買票也是不行的,黃牛人工操作,你總沒辦法吧,手工買票,就像以前的黃牛都是到火車站排隊去買票一樣。 那麼對於這三點來說,我們應該怎麼樣設計才能防止呢,一點一點來說: 一、 如何防止黃牛大量囤積票 這就是還是要從概率的方面考.
5. java秒殺系統如何實現
如果是jsp登錄PHP 那就模擬一個PHP登錄的post提交到php的登錄程序。 如果php登錄jsp 那就模擬jsp登錄的post提交到jsp的登錄程序
6. 秒殺系統架構如何設計
這種高頻系統需要考慮的因素很多。
如果在一分鍾內會有上百萬次請求, 那麼1秒鍾就要處理1萬多次請求。 那麼我們分析一下延遲:
網路延遲
系統IO延遲
內存延遲
緩存延遲
資料庫延遲
對於網路延遲,沒有很好的解決方法,這個跟用戶的網路環境有關
對於系統IO, 不太推薦用多線程以及線程池模型。 多線程創建銷毀都會有很大的額外開銷, 線程池會有等待延遲。 推薦使用libevent這類多路io的框架, 可以在一個線程內完成IO非常輕量
對於內存延遲, 如果我們在短時間內要做大量的業務,建議使用slab這類內存對象方式分配內存,這樣可以減少內存分配器帶來的開銷。 處理完的業務可以放在隊列中,可以單獨設計一個線程處理隊列來給用戶response(response延遲並不是那麼重要)。另外有大量優化的地方, 例如排除cpu緩存偽共享,集成第三方高性能內存分配器等等手段, 如果有需求可以研究一下。
一般秒殺系統session數據會放在緩存中,例如redis。 如果請求多了, 那麼流量會全部壓到一個redis的server上,會造成輕微延遲(redis是單線程隊列), 這時候可能需要做一個主從系統,不過公司的硬體環境不好有可能會有反效果, 一般情況下1s處理幾萬次請求還是沒有多大問題的。
資料庫不要動態寫,肯定慢,秒殺結束後一次性把redis的transactions 同步進去。
處理IO建議不要直接用後台伺服器, 建議做幾個io伺服器和客戶端連接, 接到客戶端請求後用rpc框架投到你的後台。 一個電腦的socket多了後性能下降很快。
7. 如何用redis和線程實現秒殺系統
寫入內存而不是寫入硬碟
傳統硬碟的讀寫性能是相當差的。SSD硬碟比傳統硬版盤快100倍。而內存權又比SSD硬碟快10倍以上。因此,寫入內存而不是寫入硬碟,就能使系統的能力提升上千倍。也就是說,原來你的秒殺系統可能需要1000台伺服器支撐,現在1台伺服器就可以扛住了。
8. PHP秒殺系統的流程是怎樣
這個就不要想了,如果誰都會寫了,誰都能秒殺了,這種東西要自己去研究的