從LiveJournal後臺發展看大規模網站效能優化方法
一、LiveJournal發展歷程
LiveJournal是99年始於校園中的專案,幾個人出於愛好做了這樣一個應用,以實現以下功能:
- 部落格,論壇
- 社會性網路,找到朋友
- 聚合,把朋友的文章聚合在一起
LiveJournal採用了大量的開源軟體,甚至它本身也是一個開源軟體。
在上線後,LiveJournal實現了非常快速的增長:
- 2004年4月份:280萬註冊使用者。
- 2005年4月份:680萬註冊使用者。
- 2005年8月份:790萬註冊使用者。
- 達到了每秒鐘上千次的頁面請求及處理。
- 使用了大量MySQL伺服器。
- 使用了大量通用元件。
二、LiveJournal架構現狀概況
三、從LiveJournal發展中學習
LiveJournal從1臺伺服器發展到100臺伺服器,這其中經歷了無數的傷痛,但同時也摸索出瞭解決這些問題的方法,通過對LiveJournal的學習,可以讓我們避免LJ曾經犯過的錯誤,並且從一開始就對系統進行良好的設計,以避免後期的痛苦。
下面我們一步一步看LJ發展的腳步。
1、一臺伺服器
一臺別人捐助的伺服器,LJ最初就跑在上面,就像Google開始時候用的破伺服器一樣,值得我們尊敬。這個階段,LJ的人以驚人的速度熟悉的Unix的操作管理,伺服器效能出現過問題,不過還好,可以通過一些小修小改應付過去。在這個階段裡LJ把CGI升級到了FastCGI。
最終問題出現了,網站越來越慢,已經無法通過優過化來解決的地步,需要更多的伺服器,這時LJ開始提供付費服務,可能是想通過這些錢來購買新的伺服器,以解決當時的困境。
毫無疑問,當時LJ存在巨大的單點問題,所有的東西都在那臺伺服器的鐵皮盒子裡裝著。
2、兩臺伺服器
用付費服務賺來的錢LJ買了兩臺伺服器:一臺叫做Kenny的Dell 6U機器用於提供Web服務,一臺叫做Cartman的Dell 6U伺服器用於提供資料庫服務。
LJ有了更大的磁碟,更多的計算資源。但同時網路結構還是非常簡單,每臺機器兩塊網路卡,Cartman通過內網為Kenny提供MySQL資料庫服務。
暫時解決了負載的問題,新的問題又出現了:
- 原來的一個單點變成了兩個單點。
- 沒有冷備份或熱備份。
- 網站速度慢的問題又開始出現了,沒辦法,增長太快了。
- Web伺服器上CPU達到上限,需要更多的Web伺服器。
3、四臺伺服器
又買了兩臺,Kyle和Stan,這次都是1U的,都用於提供Web服務。目前LJ一共有3臺Web伺服器和一臺資料庫伺服器。這時需要在3臺Web伺服器上進行負載均橫。
LJ把Kenny用於外部的閘道器,使用mod_backhand進行負載均橫。
然後問題又出現了:
- 單點故障。資料庫和用於做閘道器的Web伺服器都是單點,一旦任何一臺機器出現問題將導致所有服務不可用。雖然用於做閘道器的Web伺服器可以通過保持心跳同步迅速切換,但還是無法解決資料庫的單點,LJ當時也沒做這個。
- 網站又變慢了,這次是因為IO和資料庫的問題,問題是怎麼往應用裡面新增資料庫呢?
4、五臺伺服器
又買了一臺資料庫伺服器。在兩臺資料庫伺服器上使用了資料庫同步(Mysql支援的Master-Slave模式),寫操作全部針對主資料庫(通過Binlog,主伺服器上的寫操作可以迅速同步到從伺服器上),讀操作在兩個資料庫上同時進行(也算是負載均橫的一種吧)。
實現同步時要注意幾個事項:
- 讀運算元據庫選擇演算法處理,要選一個當前負載輕一點的資料庫。
- 在從資料庫伺服器上只能進行讀操作
- 準備好應對同步過程中的延遲,處理不好可能會導致資料庫同步的中斷。只需要對寫操作進行判斷即可,讀操作不存在同步問題。
5、更多伺服器
有錢了,當然要多買些伺服器。部署後快了沒多久,又開始慢了。這次有更多的Web伺服器,更多的資料庫伺服器,存在 IO與CPU爭用。於是採用了BIG-IP作為負載均衡解決方案。
現在伺服器基本上夠了,但效能還是有問題,原因出在架構上。
資料庫的架構是最大的問題。由於增加的資料庫都是以Slave模式新增到應用內,這樣唯一的好處就是將讀操作分佈到了多臺機器,但這樣帶來的後果就是寫操作被大量分發,每臺機器都要執行,伺服器越多,浪費就越大,隨著寫操作的增加,用於服務讀操作的資源越來越少。
由一臺分佈到兩臺
最終效果
現在我們發現,我們並不需要把這些資料在如此多的伺服器上都保留一份。伺服器上已經做了RAID,資料庫也進行了備份,這麼多的備份完全是對資源的浪費,屬於冗餘極端過度。那為什麼不把資料分佈儲存呢?
問題發現了,開始考慮如何解決。現在要做的就是把不同使用者的資料分佈到不同的伺服器上進行儲存,以實現資料的分散式儲存,讓每臺機器只為相對固定的使用者服務,以實現平行的架構和良好的可擴充套件性。
為了實現使用者分組,我們需要為每一個使用者分配一個組標記,用於標記此使用者的資料存放在哪一組資料庫伺服器中。每組資料庫由一個master及幾個slave組成,並且slave的數量在2-3臺,以實現系統資源的最合理分配,既保證資料讀操作分佈,又避免資料過度冗餘以及同步操作對系統資源的過度消耗。
由一臺(一組)中心伺服器提供使用者分組控制。所有使用者的分組資訊都儲存在這臺機器上,所有針對使用者的操作需要先查詢這臺機器得到使用者的組號,然後再到相應的資料庫組中獲取資料。這樣的使用者架構與目前LJ的架構已經很相像了。
在具體的實現時需要注意幾個問題:
- 在資料庫組內不要使用自增ID,以便於以後在資料庫組之間遷移使用者,以實現更合理的I/O,磁碟空間及負載分佈。
- 將userid,postid儲存在全域性伺服器上,可以使用自增,資料庫組中的相應值必須以全域性伺服器上的值為準。全域性伺服器上使用事務型資料庫InnoDB。
- 在資料庫組之間遷移使用者時要萬分小心,當遷移時使用者不能有寫操作。
7、現在我們在哪裡
問題:
- 一個全域性主伺服器,掛掉的話所有使用者註冊及寫操作就掛掉。
- 每個資料庫組一個主伺服器,掛掉的話這組使用者的寫操作就掛掉。
- 資料庫組從伺服器掛掉的話會導致其它伺服器負載過大。
對於Master-Slave模式的單點問題,LJ採取了Master-Master模式來解決。所謂Master-Master實際上是人工實現的,並不是由MySQL直接提供的,實際上也就是兩臺機器同時是Master,也同時是Slave,互相同步。
Master-Master實現時需要注意:
- 一個Master出錯後恢復同步,最好由伺服器自動完成。
- 數字分配,由於同時在兩臺機器上寫,有些ID可能會衝突。
解決方案:
- 奇偶數分配ID,一臺機器上寫奇數,一臺機器上寫偶數
- 通過全域性伺服器進行分配(LJ採用的做法)。
Master-Master模式還有一種用法,這種方法與前一種相比,仍然保持兩臺機器的同步,但只有一臺機器提供服務(讀和寫),在每天晚上的時候進行輪換,或者出現問題的時候進行切換。
8、現在我們在哪裡
現在插播一條廣告,MyISAM VS InnoDB。
使用InnoDB:
- 支援事務
- 需要做更多的配置,不過值得,可以更安全的儲存資料,以及得到更快的速度。
使用MyISAM:
- 記錄日誌(LJ用它來記網路訪問日誌)
- 儲存只讀靜態資料,足夠快。
- 併發性很差,無法同時讀寫資料(新增資料可以)
- MySQL非正常關閉或當機時會導致索引錯誤,需要使用myisamchk修復,而且當訪問量大時出現非常頻繁。
9、快取
去年我寫過一篇文章介紹memcached,它就是由LJ的團隊開發的一款快取工具,以key-value的方式將資料儲存到分佈的記憶體中。LJ快取的資料:
- 12臺獨立伺服器(不是捐贈的)
- 28個例項
- 30GB總容量
- 90-93%的命中率(用過squid的人可能知道,squid記憶體加磁碟的命中率大概在70-80%)
如何建立快取策略?
想快取所有的東西?那是不可能的,我們只需要快取已經或者可能導致系統瓶頸的地方,最大程度的提交系統執行效率。通過對MySQL的日誌的分析我們可以找到快取的物件。
快取的缺點?
- 沒有完美的事物,快取也有缺點:
- 增大開發量,需要針對快取處理編寫特殊的程式碼。
- 管理難度增加,需要更多人蔘與系統維護。
- 當然大記憶體也需要錢。
10、Web訪問負載均衡
在資料包級別使用BIG-IP,但BIG-IP並不知道我們內部的處理機制,無法判斷由哪臺伺服器對這些請求進行處理。反向代理並不能很好的起到作用,不是已經夠快了,就是達不到我們想要的效果。
所以,LJ又開發了Perlbal。特點:
- 快,小,可管理的http web 伺服器/代理
- 可以在內部進行轉發
- 使用Perl開發
- 單執行緒,非同步,基於事件,使用epoll , kqueue
- 支援Console管理與http遠端管理,支援動態配置載入
- 多種模式:web伺服器,反向代理,外掛
- 支援外掛:GIF/PNG互換?
11、MogileFS
LJ使用開源的MogileFS作為分散式檔案儲存系統。MogileFS使用非常簡單,它的主要設計思想是:
- 檔案屬於類(類是最小的複製單位)
- 跟蹤檔案儲存位置
- 在不同主機上儲存
- 使用MySQL叢集統一儲存分佈資訊
- 大容易廉價磁碟
到目前為止就這麼多了,更多文件可以在http://www.danga.com/words/找到。Danga.com和LiveJournal.com的同學們拿這個文件參加了兩次MySQL Con,兩次OS Con,以及眾多的其它會議,無私的把他們的經驗分享出來,值得我們學習。在web2.0時代快速開發得到大家越來越多的重視,但良好的設計仍是每一個應用的基礎,希望web2.0們在成長為Top500網站的路上,不要因為架構阻礙了網站的發展。
相關文章
- 運籌優化(十三)--大規模優化方法優化
- 大規模服務網格效能優化 | Aeraki xDS 按需載入優化
- 大型網站--前端效能優化和規範網站前端優化
- 網站從小到大發展過程網站
- 如何擴充套件大規模Web網站的效能?套件Web網站
- 網站效能優化網站優化
- 雅虎網站效能優化的34條軍規!網站優化
- 網站前端和後臺效能優化21網站前端優化
- 網站前端和後臺效能優化28網站前端優化
- Oracle效能優化方法論的發展之二:基於OWI的效能優化方法論Oracle優化
- 網站效能優化從入門到粗通(PHP 篇)網站優化PHP
- 網站的後臺地址修改,網站後臺地址修改方法網站
- Web 效能優化:21 種優化 CSS 和加快網站速度的方法Web優化CSS網站
- 從一次效能優化看https的效能優化HTTP
- Java 後臺效能優化簡要Java優化
- Java後臺效能優化簡要Java優化
- 【譯】Web 效能優化:21種優化CSS和加快網站速度的方法Web優化CSS網站
- 淺談網站效能之前端效能優化網站前端優化
- 網站內部seo優化規劃決定網站後期運營效果網站優化
- 網站效能優化實戰(二)網站優化
- 網站優化(一)——從何處著手開啟網站優化?網站優化
- Oracle效能優化方法論的發展之三:基於響應時間分析的效能優化方法論Oracle優化
- 網路效能優化常用方法優化
- Oracle效能優化方法論的發展之一:基於區域性命中率分析的效能優化方法Oracle優化
- 零信任如何跨產業規模化發展?四大安全專家同臺論道產業
- 網站效能優化:雅虎35條軍規及其可測的23條規則網站優化
- 關於網站效能優化準則網站優化
- 攀登規模化的高峰 - 螞蟻集團大規模 Sigma 叢集 ApiServer 優化實踐APIServer優化
- 使用React中後臺效能優化以及移動端優化React優化
- 使用vue中後臺效能優化以及移動端優化Vue優化
- 多維分析的後臺效能優化手段優化
- Oracle效能優化方法論的發展之六:基於流程分析和響應時間分析的效能優化方法論Oracle優化
- Oracle效能優化方法論的發展之四:基於資源瓶頸分析的優化方法論Oracle優化
- 5G to B走入規模化2.0,四大行業優先攫取發展紅利行業
- IIS網站伺服器效能優化攻略網站伺服器優化
- 網站效能優化的三重境界網站優化
- Oracle效能優化方法論的發展之五:基於工作單元的響應時間分析的效能優化方法論Oracle優化
- 怎麼修改網站後臺地址?修改公司網站的方法?網站