基本任務(wù)
中秋節(jié)的前一天,SAE突然接到一個(gè)電話(huà)禀忆,有這么一個(gè)客戶(hù)臊旭,他們專(zhuān)門(mén)給銀行、基金公司提供營(yíng)銷(xiāo)服務(wù)箩退,這回他們服務(wù)的是一個(gè)“金主”离熏,準(zhǔn)備做一個(gè)在中秋節(jié)當(dāng)天通過(guò)微信發(fā)送現(xiàn)金紅包的活動(dòng),活動(dòng)本身就是一個(gè)HTML5頁(yè)面戴涝,里面的邏輯不難滋戳,也就不到1000行代碼,大體是:
if ( 該用戶(hù)沒(méi)有參與過(guò)活動(dòng) & 余額有錢(qián))
? ? 跳轉(zhuǎn)到游戲頁(yè)面
? ? begin game
? ? 生成中獎(jiǎng)信息
? ? 扣款
? ? 調(diào)用微信紅包API
? ? end game
else
? ? 提示“已經(jīng)參與過(guò)了”啥刻,并顯示中獎(jiǎng)信息
那么問(wèn)題來(lái)了
就這么一個(gè)簡(jiǎn)單的業(yè)務(wù)奸鸯,卻困擾了這個(gè)客戶(hù)長(zhǎng)達(dá)兩年,連續(xù)兩年的中秋抽獎(jiǎng)都沒(méi)有成功過(guò)可帽,每次都以宕機(jī)=》刷不出頁(yè)面結(jié)束娄涩,作為營(yíng)銷(xiāo)公司,他們也受到了他們的客戶(hù)的質(zhì)疑蘑拯。那么前兩年的抽獎(jiǎng)活動(dòng)怎么做的呢钝满?
第一年:用自己的服務(wù)器,12核/16G內(nèi)存一臺(tái)申窘,里面跑著LAMP(Apache+MySQL+PHP)弯蚜,結(jié)果CPU跑滿(mǎn),不得不停重啟
第二年:用了某云的云服務(wù)器剃法,16核心/32G內(nèi)存碎捺,IO優(yōu)化實(shí)例一個(gè),里面跑著LAMP(同上)贷洲,結(jié)果負(fù)載巨高收厨,響應(yīng)巨慢
很不幸,兩次活動(dòng)都不成功优构,所以客戶(hù)找到了SAE诵叁。。钦椭。
分析問(wèn)題
得到需求后拧额,因?yàn)殡x最終上線(xiàn)只有一天,SAE立即派出技術(shù)團(tuán)隊(duì)到了位于北京西直門(mén)的這家上市營(yíng)銷(xiāo)公司了解情況彪腔,經(jīng)過(guò)溝通侥锦,我們來(lái)分析一下這個(gè)案例:
- 1,此次活動(dòng)的領(lǐng)域基本集中在朋友圈傳播德挣,目的是增加粉絲恭垦,并不是轉(zhuǎn)發(fā)量,所以沒(méi)有動(dòng)用大號(hào)轉(zhuǎn)發(fā),加上抽的是實(shí)際現(xiàn)金(他們的客戶(hù)要求必須現(xiàn)金不玩假抽獎(jiǎng)劵番挺,果然金主啊^_^)唠帝,很快會(huì)抽完,持續(xù)時(shí)間不長(zhǎng)建芙,所以總體量不大
- 2没隘,錢(qián)是通過(guò)微信接口預(yù)充進(jìn)去的,最麻煩的支付扣款是調(diào)用微信接口禁荸,用戶(hù)看到的就是一個(gè)標(biāo)準(zhǔn)的紅包頁(yè)面右蒲,所以免去了事務(wù)支付的重邏輯
- 3,訪(fǎng)問(wèn)的終端用戶(hù)是銀行的全國(guó)用戶(hù)赶熟,HTML5游戲里面含大量靜態(tài)元素瑰妄,原程序沒(méi)有使用CDN做資源加速
- 4,原有邏輯大量依賴(lài)MySQL數(shù)據(jù)庫(kù)映砖,且表結(jié)構(gòu)存在不合理间坐,也沒(méi)有適當(dāng)?shù)氖褂胏ache,更沒(méi)有使用讀寫(xiě)分離邑退,導(dǎo)致瞬間數(shù)據(jù)庫(kù)壓力過(guò)大
- 5竹宋,業(yè)務(wù)上沒(méi)有峰值預(yù)案,也沒(méi)有降級(jí)邏輯
- 6地技,只使用云主機(jī)蜈七,不具備自動(dòng)擴(kuò)容能力,客戶(hù)也沒(méi)有scale out的實(shí)施經(jīng)驗(yàn)
解決
考慮到這些原因莫矗,同時(shí)考慮到離實(shí)際活動(dòng)發(fā)布還有不到12個(gè)小時(shí)飒硅,不可能對(duì)原有邏輯進(jìn)行大改,所以只能放棄5(降級(jí)邏輯)
那么作谚,我們所做的工作有:
1三娩,將業(yè)務(wù)放到SAE上,因?yàn)镾AE實(shí)現(xiàn)了基于HTTP Request的container妹懒,可以隨著請(qǐng)求的增多而自動(dòng)擴(kuò)容雀监,整個(gè)過(guò)程用戶(hù)無(wú)感知也無(wú)需關(guān)心,換句話(huà)說(shuō)從1000PV到10億PV用戶(hù)無(wú)需做任何變動(dòng)即可完成眨唬,這樣首先解決Apache+PHP的運(yùn)行負(fù)載問(wèn)題
2滔悉,單單完成1是不夠的,因?yàn)樯婕暗綌?shù)據(jù)庫(kù)還是單點(diǎn)单绑,所以我們協(xié)助用戶(hù)修改數(shù)據(jù)操作為讀寫(xiě)分離,根據(jù)這個(gè)業(yè)務(wù)場(chǎng)景曹宴,用戶(hù)的錢(qián)可以有一些誤差搂橙,不是嚴(yán)格要求發(fā)放XX萬(wàn)元整(因?yàn)槭S嗟腻X(qián)微信會(huì)退回商家),于是,諸如余額是否有錢(qián)的操作不必嚴(yán)格使用tranaction保證区转,可以直接從從庫(kù)判斷
3苔巨,增加cache層,首先設(shè)置HTTP過(guò)期header和啟用CDN废离,從多個(gè)層面增加cache效果侄泽,在SAE上啟用CDN非常簡(jiǎn)單,參考http://www.sinacloud.com/doc/sae/php/cdn.html蜻韭,只要將資源地址改成CDN域名即可悼尾;使用memcache服務(wù)作為數(shù)據(jù)cache層,所有數(shù)據(jù)均從cache讀取肖方,對(duì)于需要事務(wù)的數(shù)據(jù)闺魏,使用memcache::add操作間接實(shí)現(xiàn),另外說(shuō)一句俯画,SAE上memcache不像目前的所謂的“微服務(wù)”析桥,需要用戶(hù)自己創(chuàng)建,而是SAE官方自帶的“池化”服務(wù)艰垂,每個(gè)用戶(hù)自動(dòng)可以使用多達(dá)4T的內(nèi)存cache泡仗。
4,變數(shù)據(jù)庫(kù)批量并發(fā)寫(xiě)為有限并發(fā)異步寫(xiě)猜憎,創(chuàng)建了一個(gè)TaskQueue娩怎,將所有的數(shù)據(jù)庫(kù)寫(xiě)操作放入并發(fā)度為16的Queue,通過(guò)該Queue異步update數(shù)據(jù)庫(kù)拉宗。同時(shí)峦树,SAE為企業(yè)用戶(hù)提供了最高50000 IOPS的DB實(shí)例。
5旦事,因?yàn)闀r(shí)間關(guān)系魁巩,未完成的邏輯有:變簡(jiǎn)單寫(xiě)操作從MySQL轉(zhuǎn)到KVDB(NoSQL數(shù)據(jù)庫(kù));增加業(yè)務(wù)降級(jí)開(kāi)關(guān)姐浮,緊急情況下操作HTML5客戶(hù)端隨機(jī)數(shù)谷遂,控制到達(dá)服務(wù)端的用戶(hù)數(shù)量
在完成這些修改后,應(yīng)用戶(hù)的強(qiáng)烈要求卖鲤,SAE還將這家營(yíng)銷(xiāo)公司的賬號(hào)企業(yè)等級(jí)臨時(shí)從高級(jí)型調(diào)整成最高等級(jí)(合作伙伴級(jí))一天肾扰,來(lái)準(zhǔn)備應(yīng)對(duì)中秋的秒殺活動(dòng)。至此蛋逾,我們已經(jīng)堅(jiān)信這次秒殺可以支持瞬間10萬(wàn)并發(fā)集晚,這個(gè)指標(biāo)已經(jīng)超過(guò)用戶(hù)設(shè)計(jì)的十倍,當(dāng)然区匣,客戶(hù)還是將信將疑偷拔,那么結(jié)果呢?
結(jié)果
客戶(hù)的活動(dòng)準(zhǔn)時(shí)在2015年9月27日上午10點(diǎn)整開(kāi)始:
如上圖所述,中秋槍紅包活動(dòng)發(fā)布后莲绰,最高時(shí)達(dá)到了7萬(wàn)次請(qǐng)求/秒欺旧,在紅包空了以后,請(qǐng)求迅速下降蛤签。同時(shí)辞友,從用戶(hù)日志看,沒(méi)有錯(cuò)誤日志產(chǎn)生震肮,也沒(méi)有502称龙、504等超時(shí)現(xiàn)象,根據(jù)客戶(hù)反饋钙蒙,該次活動(dòng)非常成功茵瀑,他們的客戶(hù)的現(xiàn)金紅包大約在30秒內(nèi)被搶光。之后躬厌,我們查閱了當(dāng)時(shí)memcache集群和MySQL集群的狀態(tài)马昨,所有服務(wù)參數(shù)顯示正常,證明這次秒殺行為從技術(shù)上完全滿(mǎn)足扛施。
總結(jié)
其實(shí)鸿捧,從互聯(lián)網(wǎng)的業(yè)務(wù)看,這次活動(dòng)也不算太大疙渣,畢竟客戶(hù)追求的并不是轉(zhuǎn)發(fā)量而是粉絲數(shù)匙奴,另外他們的客戶(hù)的紅包金額也不是巨大,所以這次業(yè)務(wù)的峰值量離我們的預(yù)估還有一定距離妄荔,但從這次秒殺行為還有一些經(jīng)驗(yàn)需要總結(jié)的:
1泼菌,不要迷信云服務(wù),IaaS幾乎不能幫用戶(hù)解決完全自動(dòng)的擴(kuò)容問(wèn)題啦租,SAE也只能幫用戶(hù)解決無(wú)狀態(tài)的服務(wù)擴(kuò)容哗伯,但像強(qiáng)業(yè)務(wù)邏輯的數(shù)據(jù)擴(kuò)容還是有賴(lài)于用戶(hù)自己解決,比如如果用戶(hù)還是把所有的庫(kù)篷角、表操作放到一個(gè)單點(diǎn)執(zhí)行焊刹,即使放到SAE上,也還是會(huì)出現(xiàn)瓶頸恳蹲。
2虐块,充分利用cache,cache不僅僅是利用redis或者memcache嘉蕾,而應(yīng)該是從客戶(hù)端贺奠、到代理層、到Runtime層错忱、到數(shù)據(jù)庫(kù)的各級(jí)cache儡率,同時(shí)利用cache的過(guò)期時(shí)間颁糟,合理控制cache的實(shí)效性弊端
3,變一切同步操作為異步操作喉悴,尤其是寫(xiě)數(shù)據(jù)庫(kù)的重操作,可以使用諸如TaskQueue服務(wù)來(lái)將邏輯異步化玖媚,讓整個(gè)用戶(hù)體驗(yàn)不存在阻塞邏輯
最后箕肃,還要在業(yè)務(wù)邏輯上實(shí)現(xiàn)可降級(jí)可控制,這點(diǎn)雖然因?yàn)闀r(shí)間關(guān)系未能在實(shí)際代碼上有所體現(xiàn)今魔,但是在實(shí)際大型業(yè)務(wù)確是最重要的勺像。
當(dāng)然,這里講的秒殺還不包括支付系統(tǒng)的错森,從這點(diǎn)來(lái)說(shuō)吟宦,這個(gè)案例要比淘寶、天貓等簡(jiǎn)單成千上萬(wàn)倍涩维,我們也歡迎對(duì)秒殺技術(shù)有興趣的小伙伴一起參與討論殃姓,一起提高。