1. [秒殺]搶訂單環(huán)節(jié)一般會(huì)帶來(lái)2個(gè)問(wèn)題:
1.高并發(fā):大量用戶同一時(shí)間搶購(gòu)颖变,網(wǎng)站瞬時(shí)訪問(wèn)量劇增,導(dǎo)致服務(wù)器壓力大
2.超賣: 成功下訂單買到商品的人數(shù)贺拣,超過(guò)數(shù)據(jù)庫(kù)最大庫(kù)存數(shù)量
2. [秒殺]解決方案:
前端 [擴(kuò)容蟋恬,靜態(tài)化容客,限流]:
A擴(kuò)容:
加機(jī)器埋市,這是最簡(jiǎn)單的方法悴了,通過(guò)增加前端池的整體承載量來(lái)抗峰值蛾扇。
B:靜態(tài)化
將頁(yè)面能夠靜態(tài)化的元素全部靜態(tài)化歇盼,并減少動(dòng)態(tài)元素舔痕,通過(guò)CDN來(lái)抗峰值
ESI: 在web服務(wù)器上做動(dòng)態(tài)內(nèi)容請(qǐng)求,并將數(shù)據(jù)插入靜態(tài)頁(yè)面中豹缀,用戶拿到就一個(gè)完整的頁(yè)面伯复,這種方案對(duì)服務(wù)器端性能有影響,但是用戶體驗(yàn)好
CSI:在靜態(tài)頁(yè)面中單獨(dú)發(fā)送異步j(luò)s請(qǐng)求邢笙,從服務(wù)器動(dòng)態(tài)獲取數(shù)據(jù)啸如,這種服務(wù)器效果很好,但是用戶體驗(yàn)稍差
C:限流
ip限流:針對(duì)某一個(gè)ip地址氮惯,限制單位時(shí)間內(nèi)訪問(wèn)次數(shù)
D:其他
在活動(dòng)入口的地方設(shè)置關(guān)卡游戲或者問(wèn)題環(huán)節(jié)叮雳,削弱峰值
后端出現(xiàn)高并發(fā)和超賣的原因:
I: 首先MySQL自身對(duì)于高并發(fā)的處理性能就會(huì)出現(xiàn)問(wèn)題,一般來(lái)說(shuō)妇汗,MySQL的處理性能會(huì)隨著并發(fā)thread上升而上升帘不,但是到了一定的并發(fā)度之后會(huì)出現(xiàn)明顯的拐點(diǎn),之后一路下降杨箭,最終甚至?xí)葐蝨hread的性能還要差寞焙。
II: 其次,超賣的根結(jié)在于減庫(kù)存操作是一個(gè)事務(wù)操作,需要先select捣郊,然后insert辽狈,最后update -1。最后這個(gè)-1操作是不能出現(xiàn)負(fù)數(shù)的模她,但是當(dāng)多用戶在有庫(kù)存的情況下并發(fā)操作稻艰,出現(xiàn)負(fù)數(shù)這是無(wú)法避免的懂牧。
III:最后侈净,當(dāng)減庫(kù)存和高并發(fā)碰到一起的時(shí)候,由于操作的庫(kù)存數(shù)目在同一行僧凤,就會(huì)出現(xiàn)爭(zhēng)搶InnoDB行鎖的問(wèn)題畜侦,導(dǎo)致出現(xiàn)互相等待甚至死鎖,從而大大降低MySQL的處理性能躯保,最終導(dǎo)致前端頁(yè)面出現(xiàn)超時(shí)異常旋膳。
解決方案1:
將存庫(kù)從MySQL前移到Redis中,所有的寫(xiě)操作放到內(nèi)存中途事,由于Redis中不存在鎖故不會(huì)出現(xiàn)互相等待验懊,并且由于Redis的寫(xiě)性能和讀性能都遠(yuǎn)高于MySQL,這就解決了高并發(fā)下的性能問(wèn)題尸变。然后通過(guò)隊(duì)列等異步手段义图,將變化的數(shù)據(jù)異步寫(xiě)入到DB中。
優(yōu)點(diǎn):解決性能問(wèn)題
缺點(diǎn):沒(méi)有解決超賣問(wèn)題召烂,同時(shí)由于異步寫(xiě)入DB碱工,存在某一時(shí)刻DB和Redis中數(shù)據(jù)不一致的風(fēng)險(xiǎn)。
解決方案2:
引入隊(duì)列奏夫,然后將所有寫(xiě)DB操作在單隊(duì)列中排隊(duì)怕篷,完全串行處理。當(dāng)達(dá)到庫(kù)存閥值的時(shí)候就不在消費(fèi)隊(duì)列酗昼,并關(guān)閉購(gòu)買功能廊谓。這就解決了超賣問(wèn)題。
優(yōu)點(diǎn):解決超賣問(wèn)題麻削,略微提升性能蒸痹。
缺點(diǎn):性能受限于隊(duì)列處理機(jī)處理性能和DB的寫(xiě)入性能中最短的那個(gè),另外多商品同時(shí)搶購(gòu)的時(shí)候需要準(zhǔn)備多條隊(duì)列碟婆。
解決方案3:
將寫(xiě)操作前移到Memcached中电抚,同時(shí)利用Memcached的輕量級(jí)的鎖機(jī)制CAS來(lái)實(shí)現(xiàn)減庫(kù)存操作。
優(yōu)點(diǎn):讀寫(xiě)在內(nèi)存中竖共,操作性能快蝙叛,引入輕量級(jí)鎖之后可以保證同一時(shí)刻只有一個(gè)寫(xiě)入成功,解決減庫(kù)存問(wèn)題公给。
缺點(diǎn):沒(méi)有實(shí)測(cè)借帘,基于CAS的特性不知道高并發(fā)下是否會(huì)出現(xiàn)大量更新失斨┰?不過(guò)加鎖之后肯定對(duì)并發(fā)性能會(huì)有影響肺然。
解決方案4:
將提交操作變成兩段式蔫缸,先申請(qǐng)后確認(rèn)。然后利用Redis的原子自增操作(相比較MySQL的自增來(lái)說(shuō)沒(méi)有空洞)际起,同時(shí)利用Redis的事務(wù)特性來(lái)發(fā)號(hào)拾碌,保證拿到小于等于庫(kù)存閥值的號(hào)的人都可以成功提交訂單。然后數(shù)據(jù)異步更新到DB中街望。
優(yōu)點(diǎn):解決超賣問(wèn)題校翔,庫(kù)存讀寫(xiě)都在內(nèi)存中,故同時(shí)解決性能問(wèn)題灾前。
缺點(diǎn):由于異步寫(xiě)入DB防症,可能存在數(shù)據(jù)不一致。另可能存在少買哎甲,也就是如果拿到號(hào)的人不真正下訂單蔫敲,可能庫(kù)存減為0,但是訂單數(shù)并沒(méi)有達(dá)到庫(kù)存閥值
服務(wù)器解決性能瓶頸問(wèn)題
1.排隊(duì):
可以使用消息隊(duì)列炭玫,將同步請(qǐng)求轉(zhuǎn)化成異步請(qǐng)求奈嘿,中間通過(guò)一個(gè)消息隊(duì)列在一端[隊(duì)列入口]承接瞬時(shí)的流量峰值,在另一端[隊(duì)列出口]平滑的將消息推送出去
2.設(shè)置關(guān)卡:
在活動(dòng)入口的地方設(shè)置關(guān)卡游戲或者問(wèn)題環(huán)節(jié)础嫡,削弱峰值
3.分層過(guò)濾:
秒殺請(qǐng)求先經(jīng)過(guò)CDN ==> 前端系統(tǒng) ==> 后端系統(tǒng) 過(guò)濾掉無(wú)效請(qǐng)求