轉(zhuǎn)載:1年內(nèi)4次架構(gòu)調(diào)整漩符,談Nice的服務(wù)端架構(gòu)變遷之路
Nice 本身是一款照片分享社區(qū)類型的應(yīng)用一喘,在分享照片和生活態(tài)度的同時可以在照片上貼上如品牌、地點(diǎn)嗜暴、興趣等tag凸克。
Nice從2013.10月份上線App Store到目前每天2億PV,服務(wù)端架構(gòu)經(jīng)過了4次比較大的調(diào)整(2014年年底數(shù)據(jù))闷沥。本次分享將介紹四次架構(gòu)調(diào)整的背景萎战、實踐和結(jié)果,并討論如何在人員不足的情況下平衡業(yè)務(wù)與架構(gòu)舆逃,什么樣的架構(gòu)和開發(fā)模式更適合創(chuàng)業(yè)團(tuán)隊“天下武功蚂维,唯快不破”的做事方式。
本文根據(jù)Nice技術(shù)合伙人程?在ArchSummit全球架構(gòu)師峰會上的演講整理而成路狮,點(diǎn)擊閱讀原文鏈接虫啥,查看演講視頻。
我主要是給大家?guī)硪粋€Nice服務(wù)器端從第一天到現(xiàn)在為止的整個架構(gòu)的變遷的演進(jìn)的圖奄妨,我相信大家在這個演進(jìn)的過程當(dāng)中涂籽,如果大家有自己去Run一個Startup或者加入一個Startup的時候,你可以以我們的經(jīng)驗為借鑒砸抛,看一下我們從頭開始是怎么做到一個現(xiàn)在這樣的狀態(tài)的评雌。
我可以先給大家稍微的透露一下我們現(xiàn)在的整個服務(wù)器端的一些基本的數(shù)據(jù)的情況,現(xiàn)在大概是每天五億的API的請求直焙,不包括圖片的CDN的緩存景东,一共是大概有六千萬張照片,每天新增的照片量大概在55萬奔誓,每周絕大部分的數(shù)據(jù)是增長6%左右斤吐。
Nice這一產(chǎn)品實際上是在2013年的10月份正式上線AppStore的,剛開始的時候只有iOS的版本,當(dāng)然我們是從9月份的時候曲初,正式的開始去做這個產(chǎn)品。那么在做這個產(chǎn)品的準(zhǔn)備上線的時候杯聚,我們的第一臺服務(wù)器是這樣的臼婆。這臺服務(wù)器的配置其實非常的低,它的內(nèi)存只有2G幌绍,現(xiàn)在被扔在我們辦公室的一個角落當(dāng)中颁褂,連開發(fā)機(jī)都不愿意使它。因為配置實在太低了傀广。
但就是那樣一臺服務(wù)器颁独,在Nice的初期大概撐了兩三個月左右的時間,我們才替換到別的上面伪冰。所以在非常初期的時候誓酒,其實既沒有用戶量,也沒有用戶關(guān)系贮聂,也沒有UGC的數(shù)據(jù)靠柑,一臺非常普通的戴爾的服務(wù)器,就支撐了Nice所有服務(wù)器端的功能吓懈。那么現(xiàn)在是什么樣子的呢歼冰?
2014年的10月份,首先我們自己的服務(wù)器已經(jīng)全部鳥槍換炮了耻警,當(dāng)然也不是特別高端的服務(wù)器隔嫡,是性價比非常高的一款。而且放到了北京這邊一家非常不錯的IDC當(dāng)中甘穿。熟悉運(yùn)維的同學(xué)可能知道腮恩,這個東西叫PCIe的閃存卡,是一種比SSD還要快的內(nèi)存的存儲的硬件設(shè)備扒磁,大概6到7萬塊錢一塊庆揪。因為現(xiàn)在不缺錢了,所以基本上在DB上面都用這種東西了妨托。
第一次調(diào)整架構(gòu)
那么第一次我們調(diào)整服務(wù)器架構(gòu)是在什么時候缸榛?時間是在2013年的11月份的下旬。因為隨著流量的增長兰伤,一臺機(jī)器根本不可能支撐所有的業(yè)務(wù)内颗。從現(xiàn)在來看是一個比較明智的決定,我們從自己托管的服務(wù)器遷移到了云上敦腔。我們從自己處理圖片訪問均澳,到使用圖片云存儲,這兩個事情做完了之后,基本上把我們的服務(wù)器端的人力解放出來找前,可以把絕大部分的人力投入到業(yè)務(wù)系統(tǒng)的開發(fā)當(dāng)中糟袁,并且能減少非常多的運(yùn)維的工作。
第一次演進(jìn)的時候服務(wù)器架構(gòu)調(diào)整是這樣躺盛,我們在青云上面開了五臺虛擬主機(jī)项戴,第一臺虛擬主機(jī)是做Nginx代理,同時提供Web業(yè)務(wù)的服務(wù)槽惫;還有另外兩臺虛擬主機(jī)周叮,基本上囊括了除了DB、Slave以外的其他的所有的功能界斜,包括做Web業(yè)務(wù)的處理仿耽,做DB的主庫,做圖片的存儲各薇,做Mis系統(tǒng)的后臺项贺,還有一臺就做一些日常的統(tǒng)計的Job,最后再加上兩臺DB的Master得糜。
其實非常非常的簡單敬扛,就是從第一臺單機(jī)拆成了五臺機(jī)器,當(dāng)時的數(shù)據(jù)量幾十萬PV每天朝抖,幾千張照片一天啥箭。調(diào)整的原則是,在虛擬主機(jī)上的功能能合順就合順治宣。因為當(dāng)時好像還不是很有錢急侥,所以還是比較省的。配置最高的虛擬主機(jī)是4核16G侮邀,但是基本上經(jīng)過了這一次調(diào)整之后坏怪,我們的服務(wù)器端暫時算是比較的穩(wěn)定了,這樣我們就可以把大部分的人力投入到業(yè)務(wù)的開發(fā)當(dāng)中绊茧。
這個還有一個前提條件铝宵,我們在初期的時候,包括到現(xiàn)在為止华畏,工程師一直都是非常少的鹏秋。就是這些事情,其實都是兩個工程師做得亡笑。我們服務(wù)器端工程師在很長的一段時間之內(nèi)只有兩個侣夷。
第二次調(diào)整架構(gòu)
那么這個第一次演進(jìn)完了之后,我們做了一些功能上的開發(fā)和優(yōu)化仑乌,流量又繼續(xù)在漲百拓,很快這個第一次演進(jìn)的部署方案就搞不定了琴锭,大概的時間是在2014年的3月份就出問題了。
當(dāng)時出的問題是主庫的機(jī)器壓力過大衙传,這也非常的顯而易見决帖。因為主庫上面部署了太多的東西,而主庫又非常吃IO和CPU蓖捶。于是當(dāng)時在現(xiàn)有的這個云平臺上面古瓤,做了一次架構(gòu)的升級。第一是機(jī)器按照功能進(jìn)行拆分腺阳,先把主庫給拆出來;第二個就是做一些基本的冗載和備份的工作穿香。經(jīng)過第二次演進(jìn)之后亭引,我們的整個的服務(wù)器端的架構(gòu)是這樣的。
首先我們在前面沒有只用Nginx做反向代理了皮获,我們引入了一個叫Node Blance焙蚓,其實是青云自己內(nèi)部提供的一個HA proxy,核心是這個洒宝。接下來购公,會下發(fā)到兩臺機(jī)器proxy上,這就是Nginx去做proxy雁歌。
然后我們把圖片存儲的機(jī)器和Mis的機(jī)器放在了一臺機(jī)器上宏浩。而把這上面最重的DB master給拆出來。同時我們引入了一個第三方的MySQL proxy靠瞎,這是360開源的一個MySQL proxy比庄,用它做整個DB這一塊的一個代理。
FA的機(jī)器乏盐,就是前端的機(jī)器是兩臺佳窑。因為隨著這個業(yè)務(wù)的發(fā)展,也需要引入一些新的東西父能,在這個時候神凑,我們第一次真真正正的引入了緩存。我們緩存其實直接使用的是Redis何吝。同時我們有一些異步的任務(wù)溉委,我們引入了消息隊列,我們的消息隊列用的是Beanstalk岔霸,這兩個模塊分別部署在兩臺單獨(dú)的VM的機(jī)器上薛躬。
經(jīng)過這樣一拆的話,首先第一是把主庫的壓力減輕了呆细,因為主庫我們可以配最高配置的機(jī)器型宝;其次因為有了緩存八匠,所以我們所有的大部分的壓力比較大的訪問請求或者比較頻繁的訪問請求,我們可以使用緩存去頂趴酣。第三因為引入了消息隊列梨树,我們的異步的任務(wù),其實是可以通過消息隊列去分發(fā)的岖寞。當(dāng)時的狀態(tài)抡四,大概是上千萬的請求,一天仗谆;上萬張的照片指巡,一天,主庫拆到單獨(dú)的機(jī)器隶垮,引入了三個新的模塊藻雪,最后使用了MySQL的proxy做圖片分離。
這是在2014年的3月份狸吞。很快勉耀,因為這個社交產(chǎn)品我們在整個2014年的發(fā)展還算比較順利,所以所有的東西其實都一直在漲蹋偏,直到這個時候便斥,我們的整個的服務(wù)器端的工程師依然是兩個。
第三次調(diào)整架構(gòu)
在2014年7月份的時候威始,又出現(xiàn)了新的問題枢纠,這個問題就比較麻煩,就是在青云當(dāng)時北京的機(jī)房黎棠,當(dāng)時他們可能規(guī)劃的也沒有想的特別的清楚京郑,所以對資源的配額上線做的比較小,所以我們整個的單虛擬機(jī)的可以分配的資源到了上限葫掉,8核32G些举,我想再分更多的內(nèi)存和更多的CPU,是已經(jīng)不支持了俭厚;第二個問題是單機(jī)房很快也要到達(dá)資源的上線了户魏。
因為整個北京機(jī)房的整個的資源池當(dāng)中已經(jīng)開始報警了,沒有太多的可用的空閑的資源挪挤。這種情況之下叼丑,我們就做了一個現(xiàn)在看起來是非常非常有問題的一個決定,我們決定做雙機(jī)房扛门。我們再想鸠信,既然青云北京機(jī)房,一個機(jī)房已經(jīng)搞不定了论寨,那我們再使用青云第二個機(jī)房星立,他們當(dāng)時正好上了廣東機(jī)房爽茴,也一直在Push我們?nèi)ナ褂脧V東機(jī)房。
我們做出了一個草率的決定绰垂,用雙機(jī)房室奏。然后加上容災(zāi)和備份。雙機(jī)房的部署就變得非常的復(fù)雜劲装,這個圖是我當(dāng)時做雙機(jī)房的遷移的時候畫的一個架構(gòu)圖胧沫,現(xiàn)在看起來實在是亂的已經(jīng)不能看了。
基本上是除了主庫放在北京機(jī)房以外占业,其他的所有的東西在第二個機(jī)房绒怨,原樣不動的去搭建一套一模一樣的。然后通過DNS的分流谦疾,去把流量根據(jù)地域分到不同的機(jī)房窖逗,北京和廣東的機(jī)房。當(dāng)然因為那個時候我們發(fā)現(xiàn)國外的流量也逐漸起來了餐蔬,接近10%的國外用戶,所以我們在AWS那邊也做了一套方案佑附。
這個雙機(jī)房的方案做上去了以后樊诺,又發(fā)生了一件很討厭的事情,就是你天天都在處理線上問題音同,你沒有一天能夠清靜词爬。這個的時間是在2014年的7月份,這個時候我們有兩名服務(wù)器端的工程師权均,加上一名運(yùn)維工程師顿膨。
第四次調(diào)整架構(gòu)
在部署雙機(jī)房后,我們碰到了太多的問題叽赊,讓我們大概兩個月的時間之內(nèi)恋沃,就沒有一天能夠在10點(diǎn)以前回家,因為一直有問題必指。所以我們在2014年的9月份的時候囊咏,做了第四次的演進(jìn)。第四次演進(jìn)的發(fā)現(xiàn)的問題塔橡,也就是之前我說的雙機(jī)房的問題梅割。第一個問題是MySQL的Nginx大小超過32G。這個問題基本上就無解了葛家,除非你分庫户辞。因為你青云給你的資源的上限是內(nèi)存32G,然后你發(fā)現(xiàn)MySQL的索引已經(jīng)超過了32G癞谒,然后慢查詢就爆增底燎。
第二個問題也就是雙機(jī)房最大的一個問題刃榨,互聯(lián)是不穩(wěn)定的,經(jīng)常會出現(xiàn)數(shù)據(jù)不一致的情況书蚪。因為當(dāng)時青云的雙機(jī)房喇澡,其實走的是公網(wǎng),公網(wǎng)的延遲是非常非常不穩(wěn)定的殊校,在正常的情況下晴玖,它也許是能夠在三四十毫秒。但是經(jīng)常會飆升到幾千毫秒为流。
第三個原因呕屎,就是天天加班處理線上問題,不能回家陪老婆敬察。于是大概是2014年在9月初吧秀睛,9月幾號的時候,有一次莲祸,我和我們兩個服務(wù)器端工程師和一個運(yùn)維工程師蹂安,晚上處理完問題在那吃飯,大家一邊吃飯锐帜,一邊罵娘田盈。
最后就說了一句『cao,我們還是自己干吧』缴阎。于是我們做出了允瞧,現(xiàn)在看起來還比較正確的一個決定,我們從青云遷移回來了蛮拔,到我們自己的托管服務(wù)器述暂,從雙機(jī)房回歸到單機(jī)房。
經(jīng)過第四次的演進(jìn)建炫,我們的架構(gòu)圖就變得清晰了很多畦韭。首先我們在2014年9月份的時候,第一批大概是采購了33肛跌、34臺物理機(jī)廊驼,然后做了這樣的一些部署,所有的機(jī)器都是物理機(jī)惋砂,前端是兩個HA proxy妒挎,然后用Keep alive去做護(hù)備。然后這兩個proxy的下面會連著兩個Nginx做方向代理西饵,做請求的分酝掩。然后所有的靜態(tài)資源和以及圖片全部會由Varnish去做緩存。然后我們的圖片機(jī)群用的其實是豆瓣開源出來的一套圖片和小圖片的存儲系統(tǒng)眷柔,最下層是四臺Beansdb的cluster期虾,上層使用的是Beanseye去做Proxy原朝。
由于我們還使用了七牛的鏡像存儲,所以基本上我們圖片活躍的壓力是一次镶苞,也就是所有的圖片只活躍一次喳坠,所以通過這樣的一套架構(gòu),解決了圖片存儲和備份的一個問題茂蚓。靜態(tài)資源就不用說了壕鹉,直接往Varnish里面扔。然后兩臺Nginx下面是有八臺的前端機(jī)聋涨,我們的前端是用TM晾浴,所以是八臺的TM前端機(jī)器。然后前端機(jī)器下面是四個比較大的模塊牍白,第一個是我們的NoSQL模塊脊凰,其實都不能叫它緩存了。
因為Redis現(xiàn)在在整個Nice當(dāng)中的作用已經(jīng)不止是緩存了茂腥,基本上不能掛了狸涌,掛了就掛了;第二個是MySQL最岗,MySQL依然是采用主從的方式帕胆,一主七從。第三個是Coreseek仑性,我們用Coreseek做Nice當(dāng)中的檢索和推薦。
第四個是消息隊列右蹦。當(dāng)然我們后來又大概買了诊杆,采購了十幾臺機(jī)器專門做數(shù)據(jù)平臺和數(shù)據(jù)分析的工作,有兩臺Log的收集機(jī)器何陆,再加上七八臺的Hadoop的機(jī)群晨汹。
經(jīng)過這一次的部署,我清楚的記得贷盲,這個決定大概是在2014年的九月初淘这,九月四五號做得。這個東西的上線是在2014年的九月的第二周的周末巩剖。也就是說铝穷,從我們解決做這件事情,然后到采購機(jī)器佳魔,遷機(jī)房曙聂,然后拆包裝,上架鞠鲜,裝操作系統(tǒng)宁脊,調(diào)網(wǎng)絡(luò)断国,服務(wù)遷移,一共用了一周半的時間榆苞。
那么這個事情做完了之后稳衬,非常的有意思,這個事情大概是在前一天的凌晨的四點(diǎn)鐘最終遷移完成的坐漏。做完了以后薄疚,從第二天開始,就發(fā)現(xiàn)整個世界都清靜了仙畦,再也沒收到報警了输涕。然后所有公司內(nèi)部人的反饋都是,今天怎么比昨天快了好多慨畸。
當(dāng)然這個架構(gòu)現(xiàn)在在我們看來其實是有很多的問題的莱坎,包括就是如果再過一個月的時間,讓我去做這次分享的話寸士,我們會有第五次演進(jìn)檐什。
這個架構(gòu)現(xiàn)在的問題,從我們自己的角度來看弱卡,第一個最大的問題就是它只有一個機(jī)房乃正,它是單點(diǎn)的,這個機(jī)房如果出了任何的問題婶博,整個服務(wù)是完全不可用瓮具。第二個問題是在于Redis的Cluster是沒有災(zāi)備的機(jī)制的,我們現(xiàn)在的Redis是用了四臺機(jī)器凡人,每臺機(jī)器開十個實利名党,每個實例10G的內(nèi)存,然后前端是用23:24做代理挠轴。
如果說Redis我們現(xiàn)在采用的是一致性哈希传睹,一致性哈希最大的問題就是掛了,掛了一臺機(jī)器岸晦,像我們這種情況掛了一臺機(jī)器1/4的流量就掛了欧啤,所以在Redis這塊,我們未來也要有一些比較大的改動启上。
第三塊就是雙機(jī)房的問題邢隧,這一次做雙機(jī)房,我們其實是有一定的經(jīng)驗了冈在。首先府框,我們是一定要用專線的,否則最底層的這個基礎(chǔ)設(shè)施如果不穩(wěn)定的話,你在上層做的任何東西都是掰扯迫靖;其次在做雙機(jī)房的時候院峡,當(dāng)?shù)讓拥木W(wǎng)絡(luò)能夠達(dá)到我們的要求的時候,最重要我們要引入一個消息隊列系宜。
這個消息隊列最主要的作用就是在同步數(shù)據(jù)到第二個機(jī)房照激,或者是第三個、第四個機(jī)房/因為上層如果沒有消息隊列去保證這同步數(shù)據(jù)的一致性盹牧,那么你整個的數(shù)據(jù)一致性的這個問題俩垃,未來一定會很大。所以2014年9月份至今為止汰寓,我們的架構(gòu)就是這樣的口柳。我們的穩(wěn)定性現(xiàn)在是3個9,基本上之前就是我所能今天帶給大家的全部的內(nèi)容有滑。
嘉賓介紹
程?跃闹,2008年畢業(yè)于北京郵電大學(xué),先后在百度毛好,美團(tuán)擔(dān)任后端工程師望艺,項目經(jīng)理。 2013年自主創(chuàng)業(yè)肌访,堅持一年找默,quit。 2014年1月加入Nice吼驶,負(fù)責(zé)整個技術(shù)團(tuán)隊惩激。 工作以來,從百度工程師干起蟹演,先后干過后臺內(nèi)容發(fā)布系統(tǒng)风钻,LBS相關(guān)的項目,交易相關(guān)的O2O項目轨帜,數(shù)據(jù)分析魄咕,運(yùn)維衩椒,涉獵雖廣蚌父,精通的沒有。 加入Nice以后毛萌,代碼是寫得越來越少了苟弛,主要精力放在招聘和管理,并對后端服務(wù)的穩(wěn)定性和性能做過幾次大的調(diào)整阁将。