開(kāi)發(fā)大型高負(fù)載類網(wǎng)站應(yīng)用的幾個(gè)要點(diǎn)
[打印本頁(yè)]
作者: nightsailer
時(shí)間: 2007-1-1 21:34
標(biāo)題: 開(kāi)發(fā)大型高負(fù)載類網(wǎng)站應(yīng)用的幾個(gè)要點(diǎn)
看了一些人的所謂大型項(xiàng)目的方法,我感覺(jué)都是沒(méi)有說(shuō)到點(diǎn)子上,有點(diǎn)難受。
我也說(shuō)說(shuō)自己的看法.我個(gè)人認(rèn)為,很難衡量所謂項(xiàng)目是否大型,
即便很簡(jiǎn)單的應(yīng)用在高負(fù)載和高增長(zhǎng)情況下都是一個(gè)挑戰(zhàn).因此,按照我的想法,姑且說(shuō)是高負(fù)載
高并發(fā)或者高增長(zhǎng)情況下,需要考慮的問(wèn)題.這些問(wèn)題,很多是和程序開(kāi)發(fā)無(wú)關(guān),而是和整個(gè)系統(tǒng)的
架構(gòu)密切相關(guān)的.
沒(méi)錯(cuò),首先是數(shù)據(jù)庫(kù),這是大多數(shù)應(yīng)用所面臨的首個(gè)SPOF。尤其是Web2.0的應(yīng)用,數(shù)據(jù)庫(kù)的響應(yīng)是首先要解決的。
一般來(lái)說(shuō)MySQL是最常用的,可能最初是一個(gè)mysql主機(jī),當(dāng)數(shù)據(jù)增加到100萬(wàn)以上,
那么,MySQL的效能急劇下降。常用的優(yōu)化措施是M-S(主-從)方式進(jìn)行同步復(fù)制,將查詢和操作和分別在不同的
服務(wù)器上進(jìn)行操作。我推薦的是M-M-Slaves方式,2個(gè)主Mysql,多個(gè)Slaves,需要注意的是,雖然有2個(gè)Master,
但是同時(shí)只有1個(gè)是Active,我們可以在一定時(shí)候切換。之所以用2個(gè)M,是保證M不會(huì)又成為系統(tǒng)的SPOF。
Slaves可以進(jìn)一步負(fù)載均衡,可以結(jié)合LVS,從而將select操作適當(dāng)?shù)钠胶獾讲煌膕laves上。
以上架構(gòu)可以抗衡到一定量的負(fù)載,但是隨著用戶進(jìn)一步增加,你的用戶表數(shù)據(jù)超過(guò)1千萬(wàn),這時(shí)那個(gè)M變成了
SPOF。你不能任意擴(kuò)充Slaves,否則復(fù)制同步的開(kāi)銷將直線上升,怎么辦?我的方法是表分區(qū),
從業(yè)務(wù)層面上進(jìn)行分區(qū)。最簡(jiǎn)單的,以用戶數(shù)據(jù)為例。根據(jù)一定的切分方式,比如id,切分到不同的數(shù)據(jù)庫(kù)集群去。
全局?jǐn)?shù)據(jù)庫(kù)用于meta數(shù)據(jù)的查詢。缺點(diǎn)是每次查詢,會(huì)增加一次,比如你要查一個(gè)用戶nightsailer,你首先要到
全局?jǐn)?shù)據(jù)庫(kù)群找到nightsailer對(duì)應(yīng)的cluster id,然后再到指定的cluster找到nightsailer的實(shí)際數(shù)據(jù)。
每個(gè)cluster可以用m-m方式,或者m-m-slaves方式。
這是一個(gè)可以擴(kuò)展的結(jié)構(gòu),隨著負(fù)載的增加,你可以簡(jiǎn)單的增加新的mysql cluster進(jìn)去。
需要注意的是:
1、禁用全部auto_increment的字段
2、id需要采用通用的算法集中分配
3、要具有比較好的方法來(lái)監(jiān)控mysql主機(jī)的負(fù)載和服務(wù)的運(yùn)行狀態(tài)。如果你有30臺(tái)以上的mysql數(shù)據(jù)庫(kù)在跑就明白我的意思了。
4、不要使用持久性鏈接(不要用pconnect),相反,使用sqlrelay這種第三方的數(shù)據(jù)庫(kù)鏈接池,或者干脆自己做,因?yàn)閜hp4中mysql的
鏈接池經(jīng)常出問(wèn)題。
緩存是另一個(gè)大問(wèn)題,我一般用memcached來(lái)做緩存集群,一般來(lái)說(shuō)部署10臺(tái)左右就差不多(10g內(nèi)存池)。需要注意一點(diǎn),千萬(wàn)不能用使用
swap,最好關(guān)閉linux的swap。
可能上面說(shuō)緩存的時(shí)候,有人第一想的是頁(yè)面靜態(tài)化,所謂的靜態(tài)html,我認(rèn)為這是常識(shí),不屬于要點(diǎn)了。頁(yè)面的靜態(tài)化隨之帶來(lái)的是靜態(tài)服務(wù)的
負(fù)載均衡和加速。我認(rèn)為L(zhǎng)ighttped+Squid是最好的方式了。
LVS <------->lighttped====>squid(s) ====lighttpd
上面是我經(jīng)常用的。注意,我沒(méi)有用apache,除非特定的需求,否則我不部署apache,因?yàn)槲乙话阌胮hp-fastcgi配合lighttpd,
性能比apache+mod_php要強(qiáng)很多。
squid的使用可以解決文件的同步等等問(wèn)題,但是需要注意,你要很好的監(jiān)控緩存的命中率,盡可能的提高的90%以上。
squid和lighttped也有很多的話題要討論,這里不贅述。
存儲(chǔ)也是一個(gè)大問(wèn)題,一種是小文件的存儲(chǔ),比如圖片這類。另一種是大文件的存儲(chǔ),比如搜索引擎的索引,一般單文件都超過(guò)2g以上。
小文件的存儲(chǔ)最簡(jiǎn)單的方法是結(jié)合lighttpd來(lái)進(jìn)行分布?;蛘吒纱嗍褂肦edhat的GFS,優(yōu)點(diǎn)是應(yīng)用透明,缺點(diǎn)是費(fèi)用較高。我是指
你購(gòu)買盤(pán)陣的問(wèn)題。我的項(xiàng)目中,存儲(chǔ)量是2-10Tb,我采用了分布式存儲(chǔ)。這里要解決文件的復(fù)制和冗余。
這樣每個(gè)文件有不同的冗余,這方面可以參考google的gfs的論文。
大文件的存儲(chǔ),可以參考nutch的方案,現(xiàn)在已經(jīng)獨(dú)立為hadoop子項(xiàng)目。(你可以google it)
其他:
此外,passport等也是考慮的,不過(guò)都屬于比較簡(jiǎn)單的了。
吃飯了,不寫(xiě)了,拋磚引玉而已。
作者: terry39
時(shí)間: 2007-1-2 09:42
學(xué)習(xí)~ 還沒(méi)開(kāi)發(fā)過(guò)如樓主所說(shuō)的大型項(xiàng)目?。?! 感謝分享經(jīng)驗(yàn)!
作者: kenus
時(shí)間: 2007-1-2 11:51
:victory:
作者: fengyun
時(shí)間: 2007-1-2 15:05
作者: Nickboy
時(shí)間: 2007-1-2 15:34
新手,看不太懂!
作者: geniuscynic
時(shí)間: 2007-1-2 15:39
新手,看不太懂!
作者: zhaogequ
時(shí)間: 2007-1-2 15:54
不要那么狠好不好!我們只是想用來(lái)搞點(diǎn)小玩意.
作者: programboy
時(shí)間: 2007-1-2 16:23
一直想了解大型網(wǎng)站項(xiàng)目的策劃,希望樓主以后多發(fā)此類文章
作者: forest
時(shí)間: 2007-1-2 21:06
好文章,收藏了!
作者: dzjzmj
時(shí)間: 2007-1-2 21:49
作者: yuking
時(shí)間: 2007-1-2 22:49
為什么 禁用全部auto_increment ?
作者: qinyf
時(shí)間: 2007-1-3 00:24
因?yàn)镮D已經(jīng)分布在多臺(tái)機(jī)器上了吧
作者: Yimin
時(shí)間: 2007-1-3 12:56
支持樓主分享更多的經(jīng)驗(yàn)。
希望還能給出測(cè)試數(shù)據(jù)。。。
UP。
作者: 9tmd
時(shí)間: 2007-1-3 15:04
說(shuō)了關(guān)鍵的幾個(gè)部分,還有一些比如squid群、LVS或者VIP(四層交換)之類的必須考慮,數(shù)據(jù)庫(kù)邏輯分表不需要master里面查id,可以定期緩存或者程序邏輯上進(jìn)行控制。
跟大家分享一下我的經(jīng)驗(yàn):
http://www.toplee.com/blog/archives/337.html (歡迎討論)
作者: nightsailer
時(shí)間: 2007-1-3 16:20
樓上說(shuō)的很好.
我再說(shuō)一下關(guān)于為何要在主表查詢,最主要的因素是考慮到復(fù)制和維護(hù)的問(wèn)題。假設(shè)按照程序邏輯,用戶nightsailer應(yīng)該在s1集群,但是由于種種原因,我須要將nightsailer的數(shù)據(jù)從s1集群轉(zhuǎn)移到s5集群或者某些時(shí)候,我需要將某幾個(gè)集群的數(shù)據(jù)合并,此時(shí),我維護(hù)的時(shí)候只需要更新一下主數(shù)據(jù)庫(kù)中nightsailer的cluster id從1變成5,,維護(hù)的工作可以獨(dú)立進(jìn)行,無(wú)需考慮更新應(yīng)用程序的邏輯。也許程序的id分配邏輯可以考慮到這種情況,但是這樣一來(lái),你的這個(gè)邏輯會(huì)發(fā)散到各個(gè)應(yīng)用中,產(chǎn)生的代碼的耦合是很高的。相反,采用查表這種方式,只需要在最初的時(shí)候進(jìn)行初始分配,那么其他的應(yīng)用是無(wú)需考慮這些算法和邏輯的。
當(dāng)然,我最初提到的增加這次查詢并不是說(shuō)每次查詢都需要找主數(shù)據(jù)庫(kù),緩存策略是必定要考慮的。
至于說(shuō)為什么要禁用auto_increment,我想也清楚了,數(shù)據(jù)的合并和分隔,肯定是不能用auto_increment的。
作者: nightsailer
時(shí)間: 2007-1-3 16:35
在閑扯一下,PHP的優(yōu)化可以有很多,主要的措施:
1、使用FCGI方式,配合lighttpd,Zeus.
我個(gè)人比較喜歡Zeus,簡(jiǎn)單可靠。不過(guò),需要¥¥¥。
lighty也不錯(cuò),配置文件也很簡(jiǎn)單,比較清爽。最新的1.5,雖然不穩(wěn)定,但是配合linux的aio,性能的提升
非常明顯。即便現(xiàn)在的穩(wěn)定版,使用2.6的epoll可以得到的性能是非常高。當(dāng)然,lighty比zeus缺點(diǎn)是對(duì)于smp
的支持很有限,所以可以采用多服務(wù)器負(fù)載,或者干脆起不同的進(jìn)程服務(wù)監(jiān)聽(tīng)不同的端口。
2、專門的PHP FCGI服務(wù)器。
好處多多,在這個(gè)服務(wù)器上,就跑php的fcgi服務(wù),你可以把一些緩存加上,比如xcache,我個(gè)人喜歡這個(gè)。
還有別的,套用大腕的話,把能裝的都裝上,呵呵。
另外,最主要的是,你可以只維護(hù)一個(gè)php的環(huán)境,這個(gè)環(huán)境能夠被apache,zeus,lighttpd同時(shí)share,
前提是這些都使用php的fcgi模式,而且,xcache可以充分發(fā)揮!
3、apache+mod_fastcgi
apache并非無(wú)用,有時(shí)候也需要。比如我用php做了一個(gè)web_dav的服務(wù)器,在其他有問(wèn)題,只能跑apache.
那么,apache安裝一下mod_fastcgi,通過(guò)使用externl server,使用2配置的php fastcgi。
4、優(yōu)化編譯
ICC是我的首選,就是intel的編譯器啦,用icc重新編譯php,mysql,lighty,能編的都編,會(huì)有不小的收獲的。尤其是你用
intel的cpu的話。
5、php4的64位需要patch
好像沒(méi)有人在linux x86_64上編譯過(guò)php4吧,我曾經(jīng)googleit
,別說(shuō)國(guó)內(nèi)了,連老外都很少用。
這里就做個(gè)提醒把,如果用php官方下載的(包括最新的php-4.4.4),統(tǒng)統(tǒng)無(wú)法編譯通過(guò)。問(wèn)題是出在autoconf上,需要
手工修改config.m4,一般是在mysql,gd,ldap等一些關(guān)鍵的extension上,還有phpize的腳本。把/usr/lib64加入到
config.m4中相關(guān)搜索的path中。
不過(guò)我估計(jì)很少人像我這樣死用php4不防,呵呵。php5就沒(méi)有問(wèn)題。
我也考慮正在遷移到php5.2,寫(xiě)代碼太方便了,一直忍著呢。
[
本帖最后由 nightsailer 于 2007-1-3 16:38 編輯 ]
作者: wuexp
時(shí)間: 2007-1-3 16:54
大部分跟系統(tǒng)有關(guān),對(duì)程序員來(lái)說(shuō)是透明的
作者: wuexp
時(shí)間: 2007-1-3 17:01
分表會(huì)使操作數(shù)據(jù)(更改,刪除,查詢)邊的很復(fù)雜,特別是遇到排序的時(shí)候就更麻煩了.
曾經(jīng)考慮根據(jù)用戶id哈希一下,插入到相應(yīng)的分表里
作者: nightsailer
時(shí)間: 2007-1-3 17:33
原帖由 wuexp 于 2007-1-3 17:01 發(fā)表
分表會(huì)使操作數(shù)據(jù)(更改,刪除,查詢)邊的很復(fù)雜,特別是遇到排序的時(shí)候就更麻煩了.
曾經(jīng)考慮根據(jù)用戶id哈希一下,插入到相應(yīng)的分表里
明白你的意思。
不過(guò)我們可能討論的不完全一樣,呵呵。
我所說(shuō)的分表要依據(jù)不同的業(yè)務(wù)情況來(lái)劃分的,
1、可以是垂直劃分,
比如依據(jù)業(yè)務(wù)實(shí)體切分,比如用戶a的blog貼子,用戶的tag,用戶的評(píng)論都在a數(shù)據(jù)庫(kù)u,甚者是完整的一套數(shù)據(jù)結(jié)構(gòu)(這種情況下應(yīng)該說(shuō)是分?jǐn)?shù)據(jù)庫(kù))
2、也可以水平劃分,
一個(gè)表的數(shù)據(jù)分在不同的數(shù)據(jù)庫(kù)上。
比如message表,你可能分為daily_message,history_message,
dialy_meesage可能是hot對(duì)象,week_message是warm,2個(gè)月以前的帖子
可能屬于cold對(duì)象了。這些對(duì)象依據(jù)訪問(wèn)頻度不同會(huì)劃分到不同的數(shù)據(jù)庫(kù)群上。
3、二者結(jié)合
不過(guò),不論如何,更改、刪除并不復(fù)雜,和未分區(qū)的表沒(méi)有區(qū)別。
至于查詢和排序,不可能僅僅是通過(guò)select,order吧?
而是應(yīng)該產(chǎn)生類似摘要表,索引表,參考表。。。
另外,要根據(jù)業(yè)務(wù)具體分析減少垃圾數(shù)據(jù),有些時(shí)候,只需要最初的1萬(wàn)條記錄,那么所有表
數(shù)據(jù)的排序就不需要了。很多傳統(tǒng)的業(yè)務(wù),比如零售,流水表很大,但是報(bào)表的數(shù)據(jù)
并非實(shí)時(shí)生成的,扎報(bào)表應(yīng)該不陌生。
也可以參考很多網(wǎng)站的做法,比如technorati啊,flickr之類的。
所謂的麻煩是你設(shè)計(jì)系統(tǒng)的結(jié)構(gòu)的時(shí)候要考慮到,在設(shè)計(jì)數(shù)據(jù)庫(kù)的時(shí)候更要注意,
因此只要項(xiàng)目的framework最初設(shè)計(jì)比較完備,那么可以說(shuō)大部分對(duì)開(kāi)發(fā)人員是透明的。
前提是,你一定要設(shè)計(jì)好,而不是讓程序員邊寫(xiě)代碼邊設(shè)計(jì),那會(huì)是噩夢(mèng)。
我寫(xiě)這么多廢話,并非僅僅是對(duì)程序員來(lái)說(shuō),也許對(duì)設(shè)計(jì)者更有用。
[
本帖最后由 nightsailer 于 2007-1-3 17:36 編輯 ]
作者: MySQL
時(shí)間: 2007-1-3 17:47
很好的文章。!
作者: 9tmd
時(shí)間: 2007-1-4 11:20
程序邏輯上控制表拆分只需要維護(hù)一個(gè)數(shù)據(jù)庫(kù)訪問(wèn)的配置文件即可,對(duì)于開(kāi)發(fā)來(lái)說(shuō),完全透明,可以不用關(guān)心訪問(wèn)的是哪里,而只需要調(diào)用通用的接口即可,曾經(jīng)做過(guò)的系統(tǒng)里面,這樣的應(yīng)用經(jīng)常遇到,尤其在全網(wǎng)passport、社區(qū)帖子等方面的處理上應(yīng)用最多。
原來(lái)在yahoo工作和后來(lái)mop工作都使用了這樣的架構(gòu),整體感覺(jué)來(lái)說(shuō)還是值得信賴的,單表畢竟存在面對(duì)極限數(shù)據(jù)量的風(fēng)險(xiǎn)。
作者: 9tmd
時(shí)間: 2007-1-4 11:39
前面老是有人問(wèn)auto_increment的問(wèn)題,其實(shí)這是MySQL官方專門針對(duì)M/S的Replication做過(guò)的說(shuō)明,因?yàn)镸ySQL的同步是依靠同步MySQL的SQL日志來(lái)實(shí)現(xiàn)的,事實(shí)上單向的Master->Slave使用auto_increment是沒(méi)有問(wèn)題的,而雙向的M/M模式就會(huì)存在問(wèn)題了,稍微一思考就知道怎么回事了。官方文檔:
http://dev.mysql.com/tech-resour ... ql-replication.htmlhttp://dev.mysql.com/doc/refman/ ... auto-increment.html另外,在使用MySQL的同步時(shí),需要注意在自己的代碼里面,寫(xiě)SQL的時(shí)候不要使用MySQL自己提供的類似 NOW()之類的函數(shù),而應(yīng)該使用php程序里面計(jì)算的時(shí)間帶入SQL語(yǔ)句里面,否則同步的時(shí)候也可能導(dǎo)致值不相等,這個(gè)道理可以牽涉出另外一些類似的問(wèn)題,大家可以考慮一下。
作者: wuexp
時(shí)間: 2007-1-5 11:54
原帖由 nightsailer 于 2007-1-3 17:33 發(fā)表
1、可以是垂直劃分,
比如依據(jù)業(yè)務(wù)實(shí)體切分,比如用戶a的blog貼子,用戶的tag,用戶的評(píng)論都 ...
明白業(yè)務(wù)分表,但是有時(shí)候一些基本表會(huì)隨著數(shù)據(jù)的增加回變的很大,如果mysql的表達(dá)到千萬(wàn)條數(shù)據(jù),效率會(huì)下降的非???對(duì)某條記錄進(jìn)行操作會(huì)非常容易鎖表.
兩個(gè)m,多個(gè)s,之間同步速度會(huì)隨著降低,反映速度很慢,這需要一些中間件來(lái)解決
作者: zhwb36
時(shí)間: 2007-1-6 10:45
樓主是個(gè)強(qiáng)淫!
作者: laozei
時(shí)間: 2007-2-5 15:03
原帖由 nightsailer 于 2007-1-3 16:35 發(fā)表
在閑扯一下,PHP的優(yōu)化可以有很多,主要的措施:
1、使用FCGI方式,配合lighttpd,Zeus.
我個(gè)人比較喜歡Zeus,簡(jiǎn)單可靠。不過(guò),需要¥¥¥。
lighty也不錯(cuò),配置文件也很簡(jiǎn)單,比較清爽。最新的1.5,雖然不穩(wěn)定 ...
我在linux x86_64(AMD,Centos 4.3/4.4)上編譯過(guò)php4,php5
php4費(fèi)了很大的勁才編譯好
php5裝好之后,程序運(yùn)行不正常,現(xiàn)在還繼續(xù)用著php4
從探針的探測(cè)結(jié)果來(lái)看,php4在那臺(tái)機(jī)子上的效率好像很差
,不過(guò),網(wǎng)站運(yùn)行起來(lái)好像還可以
試過(guò)xcache,那時(shí)候還是低版本,網(wǎng)站運(yùn)行不正常,就沒(méi)用了,用的是eAccelerator
web server 是lighttpd 1.4.13
作者: leidong8
時(shí)間: 2007-2-6 15:14
好!
作者: 深空
時(shí)間: 2007-5-15 11:27
上面我想有個(gè)問(wèn)題很嚴(yán)重,就是時(shí)間的問(wèn)題,數(shù)據(jù)庫(kù)分布到不同的服務(wù)器,NOW()就不同,PHP分布到不同服務(wù)器,time()也不同,我想是不是需要一個(gè)標(biāo)準(zhǔn)來(lái)獲取時(shí)間。
另外就是auto_increment的問(wèn)題,我覺(jué)得可以通過(guò)維護(hù)一張包含auto_increment的id表來(lái)實(shí)現(xiàn)INSERT的id唯一。
作者: terry39
時(shí)間: 2007-5-15 11:38
不錯(cuò)! 學(xué)到不少
作者: yagas
時(shí)間: 2007-5-15 17:04
似懂非懂的樣子~先記下來(lái)吧,以后再慢慢理解。
作者: liumingl
時(shí)間: 2007-5-15 17:41
學(xué)了很多的知識(shí)!謝謝了!