一、秒殺系統(tǒng)為什么難污桦?(難點(diǎn)在哪里针肥?)
1、場(chǎng)景分析
場(chǎng)景1:QQ即時(shí)通訊業(yè)務(wù)
業(yè)務(wù)特點(diǎn):細(xì)粒度的數(shù)據(jù)查詢
業(yè)務(wù)場(chǎng)景:
查詢個(gè)人用戶信息
查詢好友列表
查詢加入的群列表
......
場(chǎng)景分析:
上述的即時(shí)通訊的業(yè)務(wù)場(chǎng)景可看到象迎,無論是個(gè)人用戶信息撩嚼,還是好友列表,這部分?jǐn)?shù)據(jù)均是用戶自己的信息挖帘,只有自己才會(huì)查詢完丽,所以與他人發(fā)生鎖沖突的幾率極低。即使并發(fā)大拇舀,數(shù)據(jù)量大逻族,也可以通過水平切分?jǐn)?shù)據(jù)的方式進(jìn)行支持。
場(chǎng)景2:微博Feed流業(yè)務(wù)
業(yè)務(wù)特點(diǎn):讀多寫少骄崩,少量的鎖沖突
業(yè)務(wù)場(chǎng)景:
加載關(guān)注的用戶列表
獲取用戶的Feed消息列表
對(duì)消息進(jìn)行排序
返回排好序的第一頁數(shù)據(jù)
場(chǎng)景分析:
大多數(shù)的用戶都是讀取數(shù)據(jù)的操作聘鳞,只有少部分人是寫數(shù)據(jù)操作,當(dāng)讀取數(shù)據(jù)的時(shí)候要拂,對(duì)方正在寫數(shù)據(jù)時(shí)抠璃,會(huì)出現(xiàn)一定的鎖沖突。
場(chǎng)景3:秒殺業(yè)務(wù)
業(yè)務(wù)特點(diǎn):讀多寫少脱惰,少量的鎖沖突
業(yè)務(wù)場(chǎng)景:
讀取是否還有剩余商品(余票)搏嗡,是讀取操作。
搶購商品(余票)拉一,是寫入操作采盒。
剩余商品(余票)的數(shù)量是有限的,且是公用資源蔚润。
場(chǎng)景分析:
業(yè)務(wù)場(chǎng)景中磅氨,需要發(fā)生大量的讀取請(qǐng)求,讀取的是公共資源嫡纠,因?yàn)楣操Y源較少烦租,所以需要搶占資源,導(dǎo)致很多寫請(qǐng)求進(jìn)入除盏,出現(xiàn)極大的鎖沖突叉橱。
2、總結(jié)歸納
由上面的三個(gè)場(chǎng)景痴颊,我們可以看到赏迟,其實(shí)系統(tǒng)的難度是如何解決數(shù)據(jù)庫鎖沖突的問題,秒殺系統(tǒng)的讀多好解決蠢棱,我們引入緩存锌杀,即可支撐該讀多的操作甩栈,但是寫多的操作才是解決大量鎖沖突的關(guān)鍵。
二糕再、秒殺業(yè)務(wù)的架構(gòu)解決方案
架構(gòu)的解決原則:降低數(shù)據(jù)層的鎖沖突量没。
架構(gòu)的解決方案:
降讀(降低數(shù)據(jù)庫讀取操作):引入緩存
降寫(降低數(shù)據(jù)庫讀取操作):將請(qǐng)求攔截在上游
系統(tǒng)架構(gòu)的分層方案:
- 瀏覽器(前端)
- 站點(diǎn)層(Tomcat)
- 服務(wù)層(后臺(tái)服務(wù))
- 數(shù)據(jù)層(MySQL、Redis)
將請(qǐng)求攔截在上游的方案:
1突想、瀏覽器的攔截
請(qǐng)求防重處理:例如每5s只能發(fā)起一次請(qǐng)求
2殴蹄、站點(diǎn)層的攔截
去除無效請(qǐng)求:根據(jù)用戶id進(jìn)行計(jì)數(shù),控制每個(gè)用戶id猾担,5秒內(nèi)只能發(fā)起一次請(qǐng)求袭灯。
3、服務(wù)層的攔截
使用削峰限速:按庫存和數(shù)據(jù)庫抗壓能力進(jìn)行請(qǐng)求的透過绑嘹。
4稽荧、數(shù)據(jù)層
支持高可用:設(shè)置兩個(gè)數(shù)據(jù)節(jié)點(diǎn),支持高可用工腋。
架構(gòu)設(shè)計(jì)上常見的問題及解決方案:
問題1:壓力最大的在站點(diǎn)層姨丈,如何解決?
解決方案:做服務(wù)降低操作,對(duì)重復(fù)請(qǐng)求進(jìn)行默認(rèn)返回擅腰。
問題2:站點(diǎn)層如何進(jìn)行計(jì)數(shù)蟋恬?
解決方案:可以引入Redis進(jìn)行中間件計(jì)數(shù),Redis一秒可支持幾十萬個(gè)請(qǐng)求趁冈,使用Redis集群即可支持100W的請(qǐng)求歼争。
問題3:Redis為外部中間件,大量的并發(fā)會(huì)有帶寬瓶頸問題箱歧,如何解決矾飞?
解決方案:可以考慮使用服務(wù)本機(jī)內(nèi)存進(jìn)行計(jì)數(shù),雖然違背了微服務(wù)無狀態(tài)化設(shè)計(jì)呀邢,但是這部分?jǐn)?shù)據(jù)丟失對(duì)服務(wù)的影響不大,所以可以考慮豹绪。
問題4:采用內(nèi)存進(jìn)行計(jì)數(shù)价淌,如果解決用戶訪問單一服務(wù)器的問題?
解決方案:可以通過Nginx配置通過用戶id進(jìn)行分發(fā)請(qǐng)求的策略瞒津,這樣同一個(gè)用戶id就會(huì)落到同一個(gè)站點(diǎn)服務(wù)蝉衣。
問題5:為什么服務(wù)層釋放請(qǐng)求的數(shù)量要按庫存數(shù)和數(shù)據(jù)庫抗壓能力來釋放?
解決方案:如果釋放的數(shù)量大于庫存數(shù)巷蚪,一部分請(qǐng)求是失敗的病毡,給數(shù)據(jù)庫增加和浪費(fèi)系統(tǒng)IO,如果大于數(shù)據(jù)庫的抗壓能力屁柏,數(shù)據(jù)庫會(huì)發(fā)生宕機(jī)啦膜,無法辦理業(yè)務(wù)有送,那導(dǎo)致服務(wù)不可用,重啟數(shù)據(jù)庫也無法解決僧家。
三雀摘、產(chǎn)品的設(shè)計(jì)折中方案
方案1:支付和下單流程分離
業(yè)務(wù)分離,可以降低數(shù)據(jù)庫的寫壓力八拱,例如買票業(yè)務(wù)阵赠,下單后,45分鐘內(nèi)完成支付肌稻,支付業(yè)務(wù)在另一個(gè)服務(wù)內(nèi)清蚀,另一個(gè)數(shù)據(jù)庫內(nèi)。
方案2:分城市差異化銷售流程
不同班次爹谭,不同城市轧铁,在不同的時(shí)間點(diǎn)進(jìn)行銷售,完成業(yè)務(wù)的分流旦棉。
方案3:按鈕只能點(diǎn)擊一次
頁面防重點(diǎn)齿风,這樣可以減少頁面的無效請(qǐng)求。
方案4:庫存的顯示粒度加粗
例如顯示班次余票绑洛,只顯示有無余票救斑,并不顯示具體余票數(shù),這樣緩存信息只需要更新兩次真屯。
四脸候、秒殺業(yè)務(wù)的緩存結(jié)構(gòu)設(shè)計(jì)
待更新........