那啥,最近見了一人叨叨叨的神侃如何處理高並發。居然聊到服務器矩陣。我當時還沒回過神,過后細想,服務器矩陣我也知道口里說說,但是中小企業能玩得起?作為一個程序員很多時候只能用手頭資源來制定優化方案。(人生哲理:要警惕誇誇其談者)
我收集了下網上提供的處理方式列在這里。雖然我不會無聊到背下來去唬新人,但加深下映象,有個綱目還是好的。
兩大點:
通過服務器處理高並發
調整服務器應用程序池中的最大連接數。
1. 調整IIS 7應用程序池隊列長度
由原來的默認1000改為65535。
IIS Manager > ApplicationPools > Advanced Settings
Queue Length : 65535
2. 調整IIS 7的appConcurrentRequestLimit設置
由原來的默認5000改為100000。
appcmd.exe set config /section:serverRuntime /appConcurrentRequestLimit:100000
在%systemroot%/System32/inetsrv/config/applicationHost.config中可以查看到該設置。
3. 調整machine.config中的processModel>requestQueueLimit的設置
由原來的默認5000改為100000。
<configuration>
<system.web>
<processModel requestQueueLimit="100000"/>
4. 修改注冊表,調整IIS 7支持的同時TCPIP連接數
由原來的默認5000改為100000。
reg add HKLM/System/CurrentControlSet/Services/HTTP/Parameters /v MaxConnections /t REG_DWORD /d 1000000
完成上述4個設置,就可以支持10萬個同時請求
參見http://www.cnblogs.com/dudu/archive/2009/11/10/1600062.html
對於DB服務器同樣也可以調整最大連接數來做優化。
在調整優化好最大連接數之后,就只有軟硬件負載均衡了。硬件負載均衡能夠直接通過智能交換機實現,處理能力強,而且與系統無關,但是價格貴,配置困難,不 能區分實習系統與應用的狀態。所以硬件負載均衡適用於一大堆設備,大訪問量,簡單應用。軟件負載均衡是基於系統與應用的,能過更好地根據系統與應用的狀況 來分配負載。性價比高。PCL負載均衡軟件,Linux下的LVS軟件。
程序級別的並發控制:
當兩個用戶同時訪問一個頁面,一個用戶可能更新的事另一個用戶已經刪除的記錄。或者,在一個用戶加載頁面跟他點擊刪除按鈕之間的時間里,另一個用戶修改了這條記錄的內容。
ADO.NET 和 Visual Studio .NET 中的並發控制
因為數據結構基於斷開的數據,所以 ADO.NET 和 Visual Studio .NET 使用開放式並發。因此,您需要添加業務邏輯,以利用開放式並發解決問題。
如果您選擇使用開放式並發,則可以通過兩種常規的方法來確定是否已發生更改:版本方法(實際版本號或日期時間戳)和保存所有值方法。
版本號方法
在版本號方法中,要更新的記錄必須具有一個包含日期時間戳或版本號的列。當讀取該記錄時,日期時間戳或版本號將保存在客戶端。然后,將對該值進行部分更新。
處理並發的一種方法是僅當 WHERE 子句中的值與記錄上的值匹配時才進行更新。該方法的 SQL 表示形式為:
UPDATE Table1 SET Column1 = @newvalue1, Column2 = @newvalue2 WHERE DateTimeStamp = @origDateTimeStamp
或者,可以使用版本號進行比較:
UPDATE Table1 SET Column1 = @newvalue1, Column2 = @newvalue2 WHERE RowVersion = @origRowVersionValue
如果日期時間戳或版本號匹配,則表明數據存儲區中的記錄未被更改,並且可以安全地使用數據集中的新值對該記錄進行更新。如果不匹配,則將返回錯誤。 您可以編寫代碼,在 Visual Studio .NET 中實現這種形式的並發檢查。您還必須編寫代碼來響應任何更新沖突。為了確保日期時間戳或版本號的准確性,您需要在表上設置觸發器,以便在發生對行的更改 時,對日期時間戳或版本號進行更新。
保存所有值方法
使用日期時間戳或版本號的替代方法是在讀取記錄時獲取所有字段的副本。ADO.NET 中的 DataSet 對象維護每個修改記錄的兩個版本:初始版本(最初從數據源中讀取的版本)和修改版本(表示用戶更新)。當試圖將記錄寫回數據源時,數據行中的初始值將與數 據源中的記錄進行比較。如果它們匹配,則表明數據庫記錄在被讀取后尚未經過更改。在這種情況下,數據集中已更改的值將成功地寫入數據庫。
對於數據適配器的四個命令(DELETE、INSERT、SELECT 和 UPDATE)來說,每個命令都有一個參數集合。每個命令都有用於初始值和當前值(或修改值)的參數。
注意 由於不存在初始記錄,添加新記錄(INSERT 命令)只需要當前值;移除記錄(DELETE 命令)只需要使用初始值來定位要刪除的記錄。
以下示例顯示一個數據集命令的命令文本,該命令更新一個典型的客戶表。該命令是為動態 SQL 和開放式並發而指定的。
UPDATE Customers SET CustomerID = @currCustomerID, CompanyName = @currCompanyName, ContactName = @currContactName, ContactTitle = currContactTitle, Address = @currAddress, City = @currCity, PostalCode = @currPostalCode, Phone = @currPhone, Fax = @currFax WHERE (CustomerID = @origCustomerID) AND (Address = @origAddress OR @origAddress IS NULL AND Address IS NULL) AND (City = @origCity OR @origCity IS NULL AND City IS NULL) AND (CompanyName = @origCompanyName OR @origCompanyName IS NULL AND CompanyName IS NULL) AND (ContactName = @origContactName OR @origContactName IS NULL AND ContactName IS NULL) AND (ContactTitle = @origContactTitle OR @origContactTitle IS NULL AND ContactTitle IS NULL) AND (Fax = @origFax OR @origFax IS NULL AND Fax IS NULL) AND (Phone = @origPhone OR @origPhone IS NULL AND Phone IS NULL) AND (PostalCode = @origPostalCode OR @origPostalCode IS NULL AND PostalCode IS NULL); SELECT CustomerID, CompanyName, ContactName, ContactTitle, Address, City, PostalCode, Phone, Fax FROM Customers WHERE (CustomerID = @currCustomerID)
請注意,九個 SET 語句參數表示將寫入數據庫的當前值,而九個 WHERE 語句參數則表示用於定位初始記錄的初始值。
前九個 SET 語句參數對應於參數集合中的前九個參數。這些參數會將其 SourceVersion 屬性設置為 Current。
接着的九個 WHERE 語句參數用於開放式並發。這些占位符對應於參數集合中接着的九個參數,這些參數的每一個都將其 SourceVersion 屬性設置為 Original。
SELECT 語句用於在發生更新后刷新數據集。它是您在“高級 SQL 生成選項”對話框中設置“刷新數據集”選項時生成的。
注意 上面的 SQL 使用命名參數,而 OleDbDataAdapter 命令則使用問號 (?) 作為參數占位符。
默認情況下,如果您在“數據適配器配置向導”中選擇“開放式並發”選項,Visual Studio 將為您創建這些參數。此時將由您根據自己的業務要求來添加錯誤處理代碼。ADO.NET 提供了一個 DBConcurrencyException 對象,它返回違反並發規則的行。有關更多信息,請參見處理並發錯誤。
通過程序處理高並發
第一,緩存。
System.Web.Caching.Cache緩存 http://www.cnblogs.com/daizhj/archive/2007/08/15/855163.html
Memcached分布式緩存 http://www.cnblogs.com/daizhj/archive/2009/03/23/1386652.html
緩存分層(本地緩存+Memcached) http://www.cnblogs.com/daizhj/archive/2009/11/17/1604436.html
Redis架構設計 http://www.cnblogs.com/daizhj/archive/2011/02/21/1959511.html
LLServer架構設計 http://www.cnblogs.com/daizhj/archive/2011/08/26/discuznt_llserver_arch.html
跨站緩存同步 http://www.cnblogs.com/daizhj/archive/2010/06/18/discuznt_memcache_syncdata.html
小貼士
Memcached是danga.com(運營LiveJournal的技術團隊)開發的一套分布式內存對象緩存系統,用於在動態系統中減少數據庫負載,提升性能。具體的介紹可以參考:
Memcached深度分析
http://www.cnblogs.com/luluping/archive/2009/01/14/1375456.html
Redis
redis是一個key-value存儲系統。和Memcached類似,它支持存儲的value類型相對更多,包括string(字符串)、list(鏈表)、set(集合)、zset(sorted set --有序集合)和hash(哈希類型)。這些數據類型都支持push/pop、add/remove及取交集並集和差集及更豐富的操作,而且這些操作都是原子性的。在此基礎上,redis支持各種不同方式的排序。與memcached一樣,為了保證效率,數據都是緩存在內存中。區別的是redis會周期性的把更新的數據寫入磁盤或者把修改操作寫入追加的記錄文件,並且在此基礎上實現了master-slave(主從)同步。
http://doc.redisfans.com/
http://www.cnblogs.com/shanyou/archive/2012/01/28/2330451.html
第二,靜態文件分開布置
1.將用戶上傳的附件通過FTP方式傳送到另外一台服務器上。http://www.cnblogs.com/daizhj/archive/2008/07/28/1254648.html
2.通過SQUID將靜態文件緩存分布
使用SQUID做靜態前端,將論壇中的大部分靜態文件布署或外鏈到一個新的HTTP鏈接上,從而給Web服務器減壓,提升性能。
http://www.cnblogs.com/daizhj/archive/2010/06/10/1692758.html
第三,負載均衡
通過以上的方案,Web服務器壓力小了,性能也提升了,但是如果遇到更高的並發訪問量,單台Web服務器還是不能滿足需求,可以采取負載均衡的方案。
使用了LVS+KEEPALIVED、NGINX等。相關文章如下:
Discuz!NT負載均衡解決方案(HA)之---LVS(Linux Virtual Server)
http://www.cnblogs.com/daizhj/archive/2010/06/13/1693673.html
Discuz!NT負載均衡解決方案(HA)之---LVS(Linux Virtual Server)
http://www.cnblogs.com/daizhj/archive/2010/06/13/1693673.html
Discuz!NT負載均衡方案
http://www.cnblogs.com/daizhj/archive/2010/06/24/1667422.html
使用的是nginx,使用nginx作為前端負載均衡,這個確實很有吸引力,有時間能試用下就好。
第四,緩解數據庫壓力
Discuz!NT數據庫讀寫分離方案
http://www.cnblogs.com/daizhj/archive/2010/06/21/dbsnap_master_slave_database.html
全文搜索方案:
Discuz!NT企業版之Sphinx全文搜索(上)
http://www.cnblogs.com/daizhj/archive/2010/06/28/discuznt_entlib_sphinx_one.html
Discuz!NT企業版之Sphinx全文搜索(下)
http://www.cnblogs.com/daizhj/archive/2010/06/30/discuznt_entlib_sphinx_two.html
處理大數據量:
Discuz!NT千萬級數據量上的兩駕馬車--TokyoCabinet,MongoDB
http://www.cnblogs.com/daizhj/archive/2010/07/22/1781140.html
需要掌握的知識
Memcached、Redis、LLServer、SQUID、NGINX、LVS、Sphinx
有windows版本的,也有linux版本。
沒有先后,程序員應該根據需要和當下條件選用。
本地測試高並發的工具
測試方法:
本地模擬測試網站高訪問高並發采用的測試工具是大名鼎鼎的Loadrunner,這個工具做測試的一般都知道。在代震軍的博客中,有以下幾篇介紹了通過Loadrunner進行壓力並發測試。
當DiscuzNT遇上了Loadrunner(上)
http://www.cnblogs.com/daizhj/archive/2009/09/25/1573926.html
當DiscuzNT遇上了Loadrunner(中)
http://www.cnblogs.com/daizhj/archive/2009/09/27/1574897.html
當DiscuzNT遇上了Loadrunner(下)
http://www.cnblogs.com/daizhj/archive/2009/09/27/1575091.html