宅米网性能优化实践——初创互联网公司的野蛮成长
宅米是一家專注校園電子商務(wù)的互聯(lián)網(wǎng)企業(yè),目前主營校園超市O2O。公司成立于2014年11月,僅僅一年多的時(shí)間,公司即經(jīng)過4輪融資,覆蓋近200座城市,1000多所大中專院校,10000多棟宿舍樓,日均訂單20萬,峰值訂單50萬。
像所有高速發(fā)展的初創(chuàng)互聯(lián)網(wǎng)企業(yè)一樣,宅米的成長是一部野蠻成長的歷史。公司成立之初,只有三個(gè)工程師,是創(chuàng)始人CEO孫高峰在上海交通大學(xué)計(jì)算機(jī)學(xué)院和軟件學(xué)院挨個(gè)宿舍敲門敲出來,他逢人便問:『同學(xué),要不要?jiǎng)?chuàng)業(yè)?』。就這樣,三個(gè)尚未畢業(yè)休學(xué)創(chuàng)業(yè)的學(xué)生開發(fā)上線了宅米的第一個(gè)版本。
早期,為了迅速開發(fā),技術(shù)人員選擇了Ruby作為開發(fā)語言。由于業(yè)務(wù)快速增長,技術(shù)人員缺乏經(jīng)驗(yàn),系統(tǒng)甫一上線,即經(jīng)歷了各種bug,各種系統(tǒng)崩潰。往往在業(yè)務(wù)最繁忙的時(shí)候系統(tǒng)宕機(jī)了,公司上下焦頭爛額匆忙應(yīng)對(duì),工程師每天工作近20個(gè)小時(shí),困了就在桌子上趴一會(huì),醒來接著寫代碼,修bug。
但是就是在這樣的跌跌撞撞中,公司業(yè)務(wù)仍然快速增長,只幾個(gè)月的時(shí)間就成為該領(lǐng)域中最主要的競爭者,公司順利獲得A輪融資。有錢了,公司便期望在技術(shù)研發(fā)方面投入更多資源,招聘更多專業(yè)技術(shù)人才,開發(fā)出更完善更穩(wěn)定的系統(tǒng)迎接下一輪更快速的發(fā)展。但是招聘的時(shí)候才發(fā)現(xiàn),市面上Ruby工程師非常稀缺,難以招募,技術(shù)團(tuán)隊(duì)迅速?zèng)Q定轉(zhuǎn)型,使用Java作為主要的后端開發(fā)語言。于是幾個(gè)工程師一邊自己學(xué)Java,一邊招Java,不到兩個(gè)月的時(shí)間,組建了一個(gè)20多人的Java技術(shù)團(tuán)隊(duì),完成對(duì)原有幾個(gè)核心系統(tǒng)的Java重構(gòu)。
開發(fā)人員增加了,可以更加從容開展開發(fā)工作,應(yīng)對(duì)新增業(yè)務(wù)和需求變更,Bug減少了,系統(tǒng)穩(wěn)定了。但是這時(shí)候的系統(tǒng)架構(gòu)依然是一個(gè)非常簡單的Web架構(gòu),如圖1。
圖1 最開始的系統(tǒng)架構(gòu)
這樣的系統(tǒng)能不能應(yīng)對(duì)今后快速的業(yè)務(wù)發(fā)展?性能問題會(huì)不會(huì)成為持續(xù)增長的交易量的瓶頸?系統(tǒng)能不能撐得住訪問高峰期的大規(guī)模并發(fā)訪問?
性能優(yōu)化成為這個(gè)時(shí)候最重要的工作,于是安排專門的工程師進(jìn)行性能測試和性能優(yōu)化,從架構(gòu)、代碼、數(shù)據(jù)庫、運(yùn)維各個(gè)層面梳理系統(tǒng)狀況,發(fā)現(xiàn)系統(tǒng)瓶頸,進(jìn)行針對(duì)性優(yōu)化。
一、 性能測試
校園零食購物的特點(diǎn)是在晚上10點(diǎn)左右進(jìn)入高峰,在此前后一小時(shí)的交易量大概占整天交易量的一半,也就是說,如果要設(shè)計(jì)一個(gè)日訂單100萬的系統(tǒng),其實(shí)要承受的交易壓力是每小時(shí)50萬單。
當(dāng)初按照二八法則推算峰值每秒單量為556筆『500000 * 0.8 / (60 * 60 * 0.2)』,以此為基準(zhǔn)根據(jù)Nginx日志分析后端接口調(diào)用頻率,推算出接口調(diào)用比率前20的請求,以此構(gòu)造測試場景。
在執(zhí)行性能測試時(shí),我們使用Jmeter作為性能測試工具,利用了云服務(wù)提供的系統(tǒng)資源監(jiān)控作為基礎(chǔ),同時(shí)抓取應(yīng)用服務(wù)線程快照和MySQL數(shù)據(jù)庫slow.log分析系統(tǒng)瓶頸。腳本分別如下:
二、架構(gòu)優(yōu)化
性能測試結(jié)果并不樂觀,我們結(jié)合互聯(lián)網(wǎng)領(lǐng)域常用技術(shù)架構(gòu)模式以及自身性能瓶頸,進(jìn)行了架構(gòu)優(yōu)化重構(gòu)。
雖然系統(tǒng)此前使用了分布式緩存對(duì)熱點(diǎn)數(shù)據(jù)進(jìn)行緩存,但是比較隨意,哪些數(shù)據(jù)需要緩存,失效策略如何設(shè)置都沒有認(rèn)真分析和設(shè)計(jì)。性能測試后決定規(guī)范緩存使用,盡可能將各種頻繁讀取的數(shù)據(jù)全部緩存起來,并將Redis服務(wù)器做集群和主從復(fù)制部署。
此外還使用第三方CDN服務(wù)進(jìn)行靜態(tài)文件訪問加速,產(chǎn)品圖片、JavaScript文件、CSS文件等都通過CDN加速,同時(shí)通過Nginx反向代理服務(wù)器提供靜態(tài)文件的前端緩存。
性能測試發(fā)現(xiàn),系統(tǒng)主要瓶頸點(diǎn)在數(shù)據(jù)庫上,雖然使用Redis將熱點(diǎn)數(shù)據(jù)緩存起來,但是數(shù)據(jù)庫依然在并發(fā)量達(dá)到一定程度后表現(xiàn)出系統(tǒng)過載的情況。于是對(duì)數(shù)據(jù)庫進(jìn)行主從分離。
優(yōu)化后的系統(tǒng)架構(gòu)如圖2。
圖2 優(yōu)化后的系統(tǒng)架構(gòu)
三、H5響應(yīng)壓縮優(yōu)化
性能測試發(fā)現(xiàn)App應(yīng)用比移動(dòng)Web端響應(yīng)速度更快,分析發(fā)現(xiàn)H5響應(yīng)內(nèi)容因?yàn)榘舜罅縃TML,數(shù)據(jù)包大小遠(yuǎn)遠(yuǎn)大于App響應(yīng)包。因此決定采用Nginx作為反向代理的同時(shí),對(duì)HTML內(nèi)容進(jìn)行壓縮。
開啟Nginx gzip壓縮的指令如下:
關(guān)于gzip_types,我們針對(duì)JSON數(shù)據(jù)也開啟gzip壓縮,降低App響應(yīng)數(shù)據(jù)包大小,提高響應(yīng)性能。圖3是開啟gzip前后的性能測試結(jié)果對(duì)比:
圖3 H5頁面開啟壓縮前后性能對(duì)比
四、SQL語句與索引優(yōu)化
性能測試過程中發(fā)現(xiàn),由于此前主要精力都在關(guān)注如何快速實(shí)現(xiàn)業(yè)務(wù),大量數(shù)據(jù)庫查詢語句寫得比較隨意,索引設(shè)計(jì)非常不合理。
結(jié)合性能測試中Mysql數(shù)據(jù)庫slow.log分析,定位慢查詢SQL追加index,然后利用解釋執(zhí)行計(jì)劃explain優(yōu)化SQL。在此簡要列舉幾處示例。
(1) 某字段類型為varchar類型,根據(jù)查詢關(guān)鍵字段查詢時(shí),寫入值為Int類型,導(dǎo)致無法命中索引。
優(yōu)化前:
優(yōu)化后:
select * from aa where aa.bb = '1449220364536130715';(2) 查詢條件左邊寫入函數(shù),導(dǎo)致無法命中索引。
優(yōu)化前:
優(yōu)化后:
select * from cc where dd=(DATE_SUB(CURDATE(),INTERVAL 1 DAY))?(3) 追加Index時(shí),計(jì)算數(shù)據(jù)唯一性巧妙添加左前綴索引,提高索引命中率,保證索引字段唯一性。
利用如下SQL計(jì)算索引命中率:
以此算出城市拼音縮寫長度為3時(shí),命中率和唯一性比較高,則寫下如下SQL:
ALTER TABLE `city` ADD INDEX `index_on_pinyinInitial` USING BTREE (pinyin_initial(3));五、數(shù)據(jù)庫連接池優(yōu)化
數(shù)據(jù)庫的訪問優(yōu)化也比較重要,宅米后臺(tái)系統(tǒng)開發(fā)使用了Mybatis + C3P0組合,在做性能測試的時(shí)候發(fā)現(xiàn)在某些情況下有較為嚴(yán)重的性能問題。在高并發(fā)情況下,長時(shí)間施加壓力,應(yīng)用程序出現(xiàn)不能訪問的狀況。
上網(wǎng)查找資料,發(fā)現(xiàn)很多人也遇到了C3P0的”APPARENT DEADLOCK”問題。
將C3P0切換成國產(chǎn)數(shù)據(jù)庫連接池Druid之后,狀況明顯好轉(zhuǎn),類似問題再未出現(xiàn)過。
六、緩存使用優(yōu)化
經(jīng)過對(duì)數(shù)據(jù)庫和緩存應(yīng)用的一系列優(yōu)化后,緩存的命中率保持在90%以上,進(jìn)一步研究后發(fā)現(xiàn),Redis使用依然有提升的空間。
應(yīng)用程序訪問Redis的時(shí)候,可以通過使用Jedis的pipeline減少redis通信次數(shù),有效提升性能。Jedis是基于socket通信實(shí)現(xiàn)的,每次與Redis通信都會(huì)消耗相當(dāng)?shù)木W(wǎng)絡(luò)連接時(shí)間,pipeline則是以打包批量的形式執(zhí)行命令,圖4是執(zhí)行5000次set操作的響應(yīng)時(shí)間對(duì)比:
圖4 Jedis pipeline性能測試結(jié)果
七、訂單數(shù)據(jù)冷熱分離
隨著業(yè)務(wù)的持續(xù)發(fā)展,訂單表的數(shù)據(jù)會(huì)越來越多。按我們現(xiàn)在日訂單量20萬單預(yù)估,月訂單量則為600萬單,年訂單量則達(dá)到7200萬單,而且日訂單量還在不斷的增加,用不了多久,數(shù)據(jù)量就會(huì)超過MySQL的極限。
一開始我們考慮使用分布式數(shù)據(jù)庫的方案,對(duì)訂單表進(jìn)行水平切分,使用訂單號(hào)進(jìn)行hash,將訂單數(shù)據(jù)切分到多張表上。 進(jìn)一步分析后發(fā)現(xiàn),訂單數(shù)據(jù)具有明顯的冷熱不均的特點(diǎn),即剛剛創(chuàng)建的訂單是熱數(shù)據(jù),不同應(yīng)用以各種方式訪問修改這些訂單。經(jīng)過一段時(shí)間以后,特別是訂單完成后,訂單訪問頻率急劇降低,而且只有訂單查詢這一種操作。于是我們考慮采取冷熱數(shù)據(jù)分離的策略,以控制熱庫中數(shù)據(jù)總量,保障訂單表數(shù)據(jù)量始終維持在一個(gè)可以接受的范圍內(nèi),進(jìn)而提供穩(wěn)定的數(shù)據(jù)訪問性能。訂單數(shù)據(jù)冷熱分離方案如圖5。
圖5訂單數(shù)據(jù)冷熱分離
八、系統(tǒng)性能監(jiān)控
性能測試和性能優(yōu)化雖然對(duì)系統(tǒng)做了充分的改進(jìn),但是實(shí)際線上性能表現(xiàn)究竟如何,出現(xiàn)緊急性能問題時(shí)如何快速應(yīng)對(duì),還必須要對(duì)生產(chǎn)環(huán)境進(jìn)行性能監(jiān)控。在此簡要列舉一些宅米的性能監(jiān)控報(bào)警要點(diǎn):
除了系統(tǒng)自身監(jiān)控,很多系統(tǒng)故障和性能問題會(huì)直接反應(yīng)到業(yè)務(wù)上。如果系統(tǒng)響應(yīng)緩慢甚至宕機(jī),那么實(shí)時(shí)訂單量也會(huì)受到影響,因此監(jiān)控實(shí)時(shí)交易也可以發(fā)現(xiàn)系統(tǒng)問題。圖6是實(shí)時(shí)交易監(jiān)控圖,在這里例子中,21:33訂單量突然降到零,雖然系統(tǒng)監(jiān)控指標(biāo)正常,但是可以斷定系統(tǒng)必定出了問題,馬上打開應(yīng)用日志查看,發(fā)現(xiàn)有個(gè)Bug導(dǎo)致某個(gè)外部資源死鎖,立刻手工釋放該資源,系統(tǒng)恢復(fù)正常。
圖6實(shí)時(shí)訂單監(jiān)控
九、總結(jié)
性能問題是實(shí)打?qū)嵉膯栴},解決辦法也應(yīng)該針對(duì)具體問題各個(gè)擊破。通過性能測試了解系統(tǒng)現(xiàn)狀,通過瓶頸分析發(fā)現(xiàn)具體問題,針對(duì)具體問題尋找解決方案,實(shí)現(xiàn)解決方案再進(jìn)行性能測試,整個(gè)性能優(yōu)化形成閉環(huán),系統(tǒng)得以持續(xù)優(yōu)化。
經(jīng)過一系列各種性能優(yōu)化,雖然宅米主要系統(tǒng)性能現(xiàn)階段能夠滿足需求,但是技術(shù)永遠(yuǎn)要走到業(yè)務(wù)的前面,才能在業(yè)務(wù)增長以后從容應(yīng)對(duì)。而初創(chuàng)互聯(lián)網(wǎng)公司的野蠻成長速度,永遠(yuǎn)也不要猜測,技術(shù)必須要做好充分準(zhǔn)備,才能不拖業(yè)務(wù)的后腿,從容應(yīng)對(duì)各種局面。
作者介紹
胡勇,宅米網(wǎng)性能架構(gòu)師,從事軟件開發(fā)5年多,參與開發(fā)過銀行支付系統(tǒng)、高并發(fā)視頻點(diǎn)播系統(tǒng),目前專注高并發(fā)系統(tǒng)的性能優(yōu)化。
李智慧,宅米CTO,曾供職阿里巴巴與英特爾亞太研發(fā)中心,從事大型網(wǎng)站、分布式系統(tǒng)、大數(shù)據(jù)方面的研發(fā)工作。著有《大型網(wǎng)站技術(shù)架構(gòu):核心原理與案例分析》一書。
「CSDN 高級(jí)架構(gòu)師群」,內(nèi)有SDCC 2015架構(gòu)專場的講師等諸多知名互聯(lián)網(wǎng)公司的大牛架構(gòu)師,如果你想進(jìn)群交流,請加微信qshuguang2008申請入群,備注姓名+公司+職位。
(責(zé)編/ 錢曙光,關(guān)注架構(gòu)和算法領(lǐng)域,尋求報(bào)道或者投稿請發(fā)郵件qianshg@csdn.net,交流探討可加微信qshuguang2008,備注姓名+公司+職位)
本文為《程序員》原創(chuàng)文章,未經(jīng)允許不得轉(zhuǎn)載,訂閱2016年《程序員》請點(diǎn)擊 http://dingyue.programmer.com.cn
總結(jié)
以上是生活随笔為你收集整理的宅米网性能优化实践——初创互联网公司的野蛮成长的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ARES-500AI的环境配置
- 下一篇: 一个程序员修炼之道