百萬級(jí)QPS,支撐淘寶雙11需要哪些技術(shù)
前言
又到一年雙11,相信大部分同學(xué)都曾經(jīng)有這個(gè)疑問:支撐起淘寶雙11這么大的流量,需要用到哪些核心技術(shù)?性能優(yōu)化系列的第二篇我想跟大家探討一下這個(gè)話題。
完整的雙11鏈路是非常長(zhǎng)的,我當(dāng)前也沒這個(gè)實(shí)力跟大家去探討完整的鏈路,本文只跟大家探討其中的一個(gè)核心環(huán)節(jié):商品瀏覽。
商品瀏覽是整個(gè)鏈路中流量最大的或者至少是之一,這個(gè)大家應(yīng)該不會(huì)有疑問,因?yàn)閹缀趺總€(gè)環(huán)節(jié)都需要商品瀏覽。
阿里云公布的2020年雙11訂單創(chuàng)建峰值是58.3萬筆/秒,而我們?cè)谙聠吻敖?jīng)常會(huì)點(diǎn)來點(diǎn)去看這個(gè)看那個(gè)的,因此商品瀏覽肯定至少在百萬QPS級(jí)別。
廢話不多說,直接開懟。
正文
1、MySQL硬抗
不知道有沒有老鐵想過用MySQL硬抗雙11百萬QPS,反正我是沒有
,不過我們還是用數(shù)據(jù)來說說為什么不可能這么做。
根據(jù)MySQL官方的基準(zhǔn)測(cè)試,MySQL在通常模式下的性能如下圖所示:

當(dāng)然這個(gè)數(shù)據(jù)僅供參考,實(shí)際性能跟使用的機(jī)器配置、數(shù)據(jù)量、讀寫比例啥的都有影響。
首先,淘寶的數(shù)據(jù)量肯定是比較大的,這個(gè)毋庸置疑,但是無論怎么分庫分表,由于成本等原因,肯定每個(gè)庫還是會(huì)有大量的數(shù)據(jù)。
我當(dāng)前所在的業(yè)務(wù)剛好數(shù)據(jù)量也比較大,我們DBA給的建議是單庫QPS盡量控制在5000左右,實(shí)際上有可能到1萬也沒問題,但是此時(shí)可能存在潛在風(fēng)險(xiǎn)。
DBA給的這個(gè)建議值是比較穩(wěn)健保守的,控制在這個(gè)值下基本不會(huì)出問題,因此我們盡量按DBA的建議來,畢竟他們?cè)谶@方面會(huì)更專業(yè)一些。
如果按照單庫抗5000來算,即使多加幾個(gè)從庫,也就抗個(gè)十來萬QPS頂天了,要抗百萬QPS就根本不可能了,流量一進(jìn)來,DB肯定馬上跪成一片灰燼。
有同學(xué)可能會(huì)想,能不能無限加從庫硬懟?
這個(gè)是不行的,因?yàn)閺膸焓切枰加弥鲙熨Y源的,看過我之前MySQL面試題的同學(xué)應(yīng)該知道,主庫需要不斷和從庫進(jìn)行通信,傳輸binlog啥的,從庫多了主庫會(huì)受影響,無限加從庫最后的結(jié)果肯定是將主庫懟掛了,我們這邊的建議值是從庫數(shù)量盡量不要超過20個(gè),超了就要想其他法子來優(yōu)化。
2、分布式緩存(Tair)硬抗
上分布式緩存硬抗應(yīng)該是大部分老哥會(huì)想到的,我們也用數(shù)據(jù)來分析一下可行性。
阿里用的分布式緩存是自研的 Tair,不知道的可以理解為 Redis 吧,對(duì)外其實(shí)也是說的 Redis 企業(yè)版。
Tair官方自稱性能約為同規(guī)格社區(qū)版實(shí)例的3倍。阿里云官網(wǎng)上,Tair企業(yè)版性能增強(qiáng)-集群版當(dāng)前的實(shí)例規(guī)格如下圖所示:

右下角最猛的【4096GB集群性能增強(qiáng)版】的QPS參考值超過6000萬+,沒錯(cuò),我數(shù)了好幾遍,就是6000萬,我的龜龜,太變態(tài)了。
直接把【4096GB集群性能增強(qiáng)版】懟上去就解決了,還要啥優(yōu)化
。如果一個(gè)解決不了,大不了就兩個(gè)嘛。
分布式緩存確實(shí)是大多數(shù)情況下抗讀流量的主力,所以用Tair硬抗的方案肯定是沒大問題的,但是我們需要思考下是否存在以一些細(xì)節(jié)問題,例如:
分布式緩存通常放在服務(wù)端,上游通過RPC來調(diào)用獲取商品信息,百萬級(jí)的流量瞬間打進(jìn)來,是否會(huì)直接將RPC的線程池打掛?
緩存里的信息通常是先查詢DB再寫到緩存里,百萬級(jí)的流量瞬間打進(jìn)來,是否會(huì)直接將DB打掛?
是否存在熱點(diǎn)商品,導(dǎo)致Tair單節(jié)點(diǎn)扛不?。?/span>
...
這些問題我們接下來一一討論。
3、客戶端分布式緩存
分布式緩存放在服務(wù)端,我們稱之為服務(wù)端分布式緩存,但是要使用服務(wù)端分布式緩存需要上游進(jìn)行RPC調(diào)用,請(qǐng)求量太大會(huì)帶來隱患,同時(shí)帶來了額外的網(wǎng)絡(luò)請(qǐng)求耗時(shí)。
為了解決這個(gè)問題,我們引入客戶端分布式緩存,所謂客戶端分布式緩存就是將請(qǐng)求Tair的流程集成在SDK里,如果Tair存在數(shù)據(jù),則直接返回結(jié)果,無需再請(qǐng)求到服務(wù)端。
這樣一來,商品信息只要在Tair緩存里,請(qǐng)求到客戶端就會(huì)結(jié)束流程,服務(wù)端的壓力會(huì)大大降低,同時(shí)實(shí)現(xiàn)也比較簡(jiǎn)單,只是將服務(wù)端的Tair請(qǐng)求流程在SDK里實(shí)現(xiàn)一遍。
4、緩存預(yù)熱
為了解決緩存為空穿透到DB將DB打掛的風(fēng)險(xiǎn),可以對(duì)商品進(jìn)行預(yù)熱,提前將商品數(shù)據(jù)加載到Tair緩存中,將請(qǐng)求直接攔截在Tair,避免大量商品數(shù)據(jù)同時(shí)穿透DB,打掛DB。
具體預(yù)熱哪些商品了?
這個(gè)其實(shí)不難選擇,將熱點(diǎn)商品統(tǒng)計(jì)出來即可,例如以下幾類:
1)在雙11零點(diǎn)付款前,大部分用戶都會(huì)將要買的商品放到購物車,因此可以對(duì)購物車的數(shù)據(jù)進(jìn)行一個(gè)統(tǒng)計(jì),將其中的熱點(diǎn)數(shù)據(jù)計(jì)算出來即可。
2)對(duì)一些有參與優(yōu)惠或秒殺活動(dòng)的商品進(jìn)行統(tǒng)計(jì),參與活動(dòng)的商品一般也會(huì)被搶購的比較厲害。
3)最近一段時(shí)間銷量比較大的商品,或者瀏覽量比較大的商品。
4)有參與到首頁活動(dòng)的商品,最近一段時(shí)間收藏夾的商品等等...
淘寶背后有各種各樣的數(shù)據(jù),統(tǒng)計(jì)出需要預(yù)熱的商品并不難。
通過預(yù)熱,可以大大降低DB被穿透的風(fēng)險(xiǎn)。
5、本地緩存
阿里云官網(wǎng)的數(shù)據(jù)【4096GB集群性能增強(qiáng)版】的QPS參考值超過6000萬+,但是這個(gè)值是在請(qǐng)求分布比較均勻的情況下的參考值,256個(gè)分片上每個(gè)分片二三十萬這樣。
通常個(gè)別分片高一點(diǎn)也沒事,五六十萬估計(jì)也ok,但是一般不能高太多,否則可能出現(xiàn)帶寬被打滿、節(jié)點(diǎn)處理不過來等情況,導(dǎo)致整個(gè)集群被打垮。
這個(gè)時(shí)候就需要祭出我們的最終神器了,也就是本地緩存。本地緩存的性能有多牛逼了,我們看下這張圖。
這張圖是caffeine(一個(gè)高性能Java緩存框架)官方提供的本地測(cè)試結(jié)果,并不是服務(wù)器上的測(cè)試結(jié)果。
測(cè)試運(yùn)行在 MacBook Pro i7-4870HQ CPU @ 2.50GHz (4 core) 16 GB Yosemite系統(tǒng),簡(jiǎn)單來說,比較一般的配置,大部分服務(wù)器配置應(yīng)該都會(huì)比這個(gè)高。
在這個(gè)基準(zhǔn)測(cè)試中, 8 線程對(duì)一個(gè)配置了最大容量的緩存進(jìn)行并發(fā)讀。

可以看到,caffeine支持每秒操作數(shù)差不多是1.5億,而另一個(gè)常見的緩存框架Guava差不多也有2000多萬的樣子。
而在服務(wù)器上測(cè)試結(jié)果如下:
服務(wù)器配置是單插槽 Xeon E5-2698B v3 @ 2.00GHz (16 核, 禁用超線程),224 GB,Ubuntu 15.04。

可以看到caffeine在使用16線程時(shí)支持每秒操作數(shù)已經(jīng)達(dá)到3.8億次,其他的框架也基本都是千萬級(jí)以上。
通過上面的數(shù)據(jù),大家應(yīng)該都明白了,本地緩存在抗讀流量上理論上是無敵的。當(dāng)然本地緩存有一些缺點(diǎn),例如需要占用服務(wù)器的本地內(nèi)存,因此通常我們只會(huì)存儲(chǔ)少量的熱點(diǎn)數(shù)據(jù),嚴(yán)格配置好參數(shù),控制好本地緩存的占用內(nèi)存上限,避免影響服務(wù)器本身的使用。
因此,我們會(huì)對(duì)之前的熱點(diǎn)數(shù)據(jù),再進(jìn)行一次篩選,選出“熱點(diǎn)中的熱點(diǎn)”,將這些數(shù)據(jù)提前預(yù)熱到本地緩存中。
可能有同學(xué)會(huì)問,如果本地緩存里的商品數(shù)據(jù)發(fā)生了變更,怎么辦?
一個(gè)辦法是使用類似ZK的監(jiān)聽方式,當(dāng)本地緩存的商品發(fā)生變更時(shí),觸發(fā)更新操作,本地緩存去拉取最新數(shù)據(jù),因?yàn)楸镜鼐彺娴纳唐窋?shù)較少,所以ZK整體壓力不會(huì)太大。
另一個(gè)辦法是本地緩存定期拉取最新數(shù)據(jù),例如每隔N秒后,就主動(dòng)查詢一次DB,將數(shù)據(jù)更新為最新數(shù)據(jù),具體延遲幾秒,根據(jù)業(yè)務(wù)上能接受的來控制。
具體選哪種看業(yè)務(wù)的選擇吧,這些被篩選進(jìn)入本地緩存的數(shù)據(jù)基本都是最熱的那些商品,無論是商家還是運(yùn)營(yíng)都心里有數(shù),肯定在活動(dòng)前會(huì)再三確認(rèn),所以出現(xiàn)變更的幾率其實(shí)不大。
6、訪問DB加鎖
盡管我們對(duì)熱點(diǎn)數(shù)據(jù)進(jìn)行了預(yù)熱,但是我們必須考慮到可能會(huì)有這么一些緩存擊穿的場(chǎng)景:
1)某個(gè)熱點(diǎn)數(shù)據(jù)在緩存里失效了,大量流量瞬間打到DB,導(dǎo)致DB被打垮。
2)某個(gè)商品并不屬于熱點(diǎn)商品,所以并沒有預(yù)熱,但是在活動(dòng)開始后成為熱點(diǎn)商品,導(dǎo)致流量大量打到DB,DB被瞬間打垮。
等等,這些場(chǎng)景都可能會(huì)導(dǎo)致DB瞬間被打垮,DB是生命線,DB一掛就涼了,因此我們必須要有相應(yīng)的措施來應(yīng)對(duì)。
解決方案在之前講緩存擊穿的文章里其實(shí)提過了,就是在訪問DB時(shí)加鎖,保證單臺(tái)服務(wù)器上對(duì)于同一個(gè)商品在同一時(shí)刻,只會(huì)有一個(gè)線程去請(qǐng)求DB,其他的全部原地阻塞等待該線程返回結(jié)果。
注意,這邊我們是不會(huì)加分布式鎖的,只會(huì)加JVM鎖,因?yàn)镴VM鎖保證了在單臺(tái)服務(wù)器上只有一個(gè)請(qǐng)求走到數(shù)據(jù)庫,通常來說已經(jīng)足夠保證數(shù)據(jù)庫的壓力大大降低,同時(shí)在性能上比分布式鎖更好。這個(gè)在Guava中就有現(xiàn)成的實(shí)現(xiàn),有興趣的可以看看。
7、熱點(diǎn)探測(cè)
我們上述所說的熱點(diǎn)商品都是基于已有數(shù)據(jù)的分析,屬于靜態(tài)數(shù)據(jù),難免會(huì)有漏掉的,因此也需要有辦法能實(shí)時(shí)的探測(cè)出熱點(diǎn)數(shù)據(jù),從而進(jìn)行緩存,保護(hù)系統(tǒng)穩(wěn)定。
8、限流
無論你想的多么齊全,真正面臨線上考驗(yàn)的時(shí)候,經(jīng)常會(huì)出現(xiàn)一些你沒考慮到的情況,因此,我們必須要有最終的保護(hù)措施。
限流降級(jí)作為最后一道防御墻,不到萬不得已我們不希望使用到他,但是我們必須做好準(zhǔn)備,萬一發(fā)生沒預(yù)料到的情況,可以保證大部分用戶不會(huì)受到影響。
9、全鏈路壓測(cè)
模擬雙11當(dāng)天的流量進(jìn)行測(cè)試,系統(tǒng)到底能抗多少,只有壓測(cè)一下才知道,同時(shí)壓測(cè)出來的指標(biāo),也會(huì)作為我們?cè)O(shè)置限流值很重要的參考依據(jù)。
10、預(yù)案
預(yù)案是指根據(jù)評(píng)估分析或經(jīng)驗(yàn),對(duì)潛在的或可能發(fā)生的突發(fā)事件的類別和影響程度而事先制定的應(yīng)急處置方案。
簡(jiǎn)單來說就是關(guān)鍵時(shí)刻一鍵拉閘,直接切換某些功能或者關(guān)閉降級(jí)某些功能,以保障核心功能不會(huì)受到影響。
11、降級(jí)部分非核心功能
在雙11高峰期將一些非核心功能進(jìn)行降級(jí),避免影響核心流程,例如我記得訂單是超過幾個(gè)月就不讓查。
12、監(jiān)控大盤
各項(xiàng)核心指標(biāo)都需要有監(jiān)控和告警,例如:緩存命中率、服務(wù)端請(qǐng)求QPS、DB讀寫QPS等等。
同時(shí)要設(shè)置合理的告警值,萬一出現(xiàn)異??梢约皶r(shí)感知及時(shí)解決。
同時(shí)要有一個(gè)核心業(yè)務(wù)監(jiān)控大盤,放置最核心的業(yè)務(wù)指標(biāo)監(jiān)控,方便大家及時(shí)了解業(yè)務(wù)核心指標(biāo)情況。
13、加機(jī)器
雖然很多人會(huì)看不起加機(jī)器解決,但是實(shí)際上加機(jī)器是必不可少的,簡(jiǎn)單粗暴,花錢就能解決。
14、其他
以上列的只是我當(dāng)前能想到的,實(shí)際上肯定比這要多的多。
最后
我是囧輝,一個(gè)堅(jiān)持分享原創(chuàng)技術(shù)干貨的程序員。
由于本人實(shí)力有限難免會(huì)有錯(cuò)誤,歡迎大家指教,如果有疑問,也歡迎留言探討。
推薦閱讀
最近我將面試:阿里、字節(jié)、美團(tuán)、快手、拼多多等大廠的高頻面試整理出來,并按大廠的標(biāo)準(zhǔn)給出自己的解析。
群里有不少同學(xué)看完拿下了阿里、美團(tuán)等大廠 Offer,希望能助你一臂之力,早日拿下大廠 Offer。
獲取方式:點(diǎn)擊【在看】,關(guān)注公眾號(hào)回復(fù)【面試】即可領(lǐng)取,更多大廠面試真題解析 PDF 整理中。

