一個RoR的站點性能優化的故事(2)原文鏈接: http:///articles/2006/03/20/the-adventures-of-scaling-stage-2 中文鏈接: http:///2009/08/01/00/12/一個ror的站點性能優化的故事2.html 圣誕節前 11月份,仍然還在舊系統的框架下,一些新的想法還是出的比較慢。 這并不能說是一次失敗,我們嘗試將一些可能的影響性能的因素都做了調整。 首先,我們用源碼重新編譯 了Ruby,而不是使用Debian系統提供的二進制包。Debian有些時候基于某種考慮打了一些不太正規的補丁。在某些情況下,這樣不失為一種好辦 法,然而為了性能,我們還是從源碼重新安裝了Ruby,甚至安裝了專為i686優化過的libc6包。 與此同時,我們還將Debian提供的Mysql二進制包,改成了Mysql官方提供的安裝包,并且將版本從5.0.16升級到5.0.17。 (譯者評:Debian/Ubuntu這類linux發行版中,還是自己編譯吧) 一般說來,Mysql5已經被證明是非常穩定的產品。我們曾經碰到過一點點數據同步復制 的問題(master-master中有出現重復自增ID的情況,這個在5.0.19中已經修復了這個bug),但有時候Mysql數據庫每秒中查詢達到 2000-3000次的時候,后臺守護進程經常會在幾個月內崩潰一兩次。 讓我們具體談談Mysql吧
如果針對數據庫的配置錯誤或者優化不好的話,它很容易拖慢整個系統。有許多書都是專門講數據庫優化的比如whole books和 webinars 。我在這里就簡單的介紹一下。 eins.de利用了Mysql的 全文檢索 Full TEXT來做搜索功能。MyISAM存儲引擎不能支持事務。你可以用InnoDB和MyISAM兩種引擎結合起來用。 解決問題有一下幾個辦法: 1.另買一臺數據庫服務器,用MySIAM類型的表,然后從類型是InnoDB的 Master數據庫表中(我聽說Flickr是這么做的)。然而這樣就需要仔細的設計程序,得以突破Rails的局限性,Rails不能很好的區分讀數據 庫和寫數據庫。即便能這么弄,我們也不會走這條技術路線,因為我們沒有預算來買第三臺數據庫服務器。 2.不去使用全文檢索, 可以使用類似Ruby-Odeum 這樣的搜索引擎。這里面比較頭疼的是,如何讓數據庫地更新時,同時搜索引擎索引也重建索引保持數據同步。這條路我們也不選擇。 這樣我們最終使用了一種混合的方式。 當前,可用的內存有4G,將它分成InnoDB和MyISAM兩部份。2/3的內存給InnoDB用(因為這系統主要的表用的是InnDB,還用于緩存MyISM表的索引數據) 剩下的1/3是給MyISAM的。另外,我們使用了查詢SQL結果的大緩存,也就是Mysql中的query cache。(這個參數是否被用起來了可以通過Mysql的show status命令來看) 我們數據庫參數設置如下: key_buffer=700M myisam_sort_buffer_size=128M query_cache_size=64M innodb_buffer_pool_size=1600M 如果前端的分發器是單個服務器,并且是持久連接,數據庫連接數的參數設置就沒有什么必要了。 繼續進行應用服務器的優化 對于系統進行反復的研究找出一共有多少請求是非常有用的。這個是沒有“一勞永逸”的解決辦法。一般說來,你需要包含系統高峰時期并且不能當機,如此大量的線程并行運行以至于機器變慢,這是因為對于CPU來說線程相互之間是阻塞的。 以前我們在每臺服務器上設置20個并發時,系統的負載一般都是在30或30以上。事情進展的非常順利,我們降低了并發數量。這樣的效果非常明顯。 通過簡單的計算,我們從一天PV數量計算出整個的監聽數量。eins.de那時大概每天100萬PV,所有的用戶都在同一個時區,訪問遍布在一天的14個小時中(從早上9點到晚上11點)。我們再做一個簡單的計算: 1M page requrest / 14 hours = 20 requests per second 假設系統平均處理每個頁面請求都會少于1秒中,那么我們需要20個并發進程來監聽請求。以上計算是根據平均值進行的,為了能夠處理高峰時的峰值,我們將每臺應用服務器的監聽數目從10減小到7,這樣四臺應用服務器加起來一共有28個監聽,應該能滿足當前壓力的要求。 (譯者評:一般峰值是平均值的5-10倍,根據各自的網站特點來確定)
另外,每臺機器上安裝的Rails從0.14.4逐步升級到了1.0.雖然這對性能不一定有幫助,但是說不定是有用的。 到了11月中旬,據報道Linux 內核2.6對于性能、內存管理和進程管理等等都是非常好的,因此我們將所有的系統的內核從2.4.27升級到了2.6.14。 大家對這個內核升級對性能的提升將信將疑,后來根據監控軟件Cacti的顯示,系統升級后確實提高了不少。數據庫服務器雖然提高不少,但應用服務器的負載卻 下降得非常明顯。記錄顯示內核的升級使得系統在高峰時期的負載從8降到了5。 升級內核所取得的效果讓我們有了些興奮,我們繼續所做的事情是將應用服務器的壓力再次給到兩臺數據庫服務器上。在此以前,所有的壓力都是由一臺機器支撐的,另外一臺只是安靜的呆在那兒復制主力數據庫的數據,僅僅是主力壞了它來頂上的災難恢復而存在的。 我們沒有去考慮haproxy的災難恢復,只是簡單的將請求按照2:1的比率分配到兩臺數據庫服務器上。 在寫的壓力很大的時候,偶爾會出現兩臺數據庫同步不能跟上的問題,直到 一臺的寫處理完才能恢復。如果碰上幾秒鐘這種倒霉的事情,一個用戶可能一次請求在一臺數據庫服務器上,而另外一次則在另一臺上,這樣就比較尷尬。舉一個最 糟糕的例子,AJAX開始的時候請求了一臺機器,而后AJAX執行的操作卻從另外一臺獲得,數據是不同步的造成了混亂。 為了減少寫操作,我們經用戶證明發現在用戶沒有獲取任何有用數據的時候,系統不僅通過ActiveRecordStore 更新了session,而且更新了用戶的在線狀態表和token數據。事實是,雖然多個MySQL線程能夠更新多張表(甚至能通過InnoDB的行級鎖來 一次更新一張表里面的多行),但是你只能有一個線程來處理將所有的寫操作寫到另外一臺服務器上。這個問題困擾了我們不止一次。 另外,我們將緩存memcached在兩個數據庫上移來移去以更好的分攤機器的壓力,讓另外一臺機器來處理廣告信息phpAdsNew(譯者評:一個廣告投放系統) 在11月底,我們完成了以上這些事情,到目前為止我們已經多次達到了百萬PV的情況,流量每天已經達到了85G。 整個系統配置如下: 到此系統調優的文章已經寫了2/3,后續文章將會包括memcached的最佳實踐,session的優化以及更多系統優化技術。 |
|
來自: 漂在北方的狼 > 《Architecture》