1. 商品列表頁(yè),用戶瀏覽商品
2. 點(diǎn)擊進(jìn)入某個(gè)商品的詳情頁(yè)
3. 進(jìn)入商品詳情頁(yè)后
• 秒殺未開(kāi)始顯示秒殺倒計(jì)時(shí)
• 秒殺已開(kāi)始顯示秒殺按鈕
• 秒殺已結(jié)束顯示秒殺結(jié)束
4. 用戶在商品詳情頁(yè)點(diǎn)擊秒殺按鈕后
① 驗(yàn)證商品id和秒殺唯一標(biāo)志是否合法 (秒殺唯一標(biāo)識(shí):暴露秒殺地址)
② 判斷秒殺時(shí)間是否開(kāi)始
判斷商品的秒殺開(kāi)始時(shí)間和結(jié)束時(shí)間,用當(dāng)前系統(tǒng)時(shí)間和他們做比較
③ 判斷秒殺是否搶光了
判斷Redis中該商品的庫(kù)存>0可以秒殺,<=0秒殺結(jié)束
④ 判斷用戶是否已經(jīng)秒殺過(guò)該商品
判斷Redis中的key是否存在,用戶秒殺后會(huì)在Redis中設(shè)置一個(gè)占位的key來(lái)標(biāo)識(shí)用戶已經(jīng)秒殺過(guò)該商品
5. 判斷當(dāng)前系統(tǒng)流量是否已經(jīng)超過(guò)閾值
• 通過(guò)Redis的List數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)
• 每有一個(gè)用戶請(qǐng)求,就將用戶的請(qǐng)求放入List
• 當(dāng)List的長(zhǎng)度達(dá)到我們?cè)O(shè)置的最大值后(通常設(shè)置為商品庫(kù)存數(shù)的100倍等)
• 拒絕后續(xù)用戶的訪問(wèn),減輕系統(tǒng)的壓力
• 用戶秒殺流程執(zhí)行結(jié)束后,不管是秒殺成功還是失敗,都需要將限流的List彈出一個(gè)元素,以便于讓后面的人可以再進(jìn)來(lái)一個(gè)
7. 進(jìn)行秒殺
① 減庫(kù)存
在redis中減庫(kù)存,采用redis減庫(kù)存 decrBy 方法(單線程的操作,不會(huì)產(chǎn)生數(shù)據(jù)沖突)
我們數(shù)據(jù)庫(kù)中并沒(méi)有直接減庫(kù)存,因?yàn)閿?shù)據(jù)庫(kù)性能瓶頸問(wèn)題
最終我們采用定時(shí)任務(wù)每隔幾秒同步一次Redis庫(kù)存到數(shù)據(jù)庫(kù),讓數(shù)據(jù)庫(kù)的庫(kù)存和redis的庫(kù)存同步
② 下訂單
• 異步下訂單,也是為了避免直接操作數(shù)據(jù)庫(kù)
• 采用隊(duì)列ActiveMQ下訂單
• 減庫(kù)存成功后,給MQ發(fā)一個(gè)消息
• 消息監(jiān)聽(tīng)器接收到消息后在數(shù)據(jù)庫(kù)創(chuàng)建訂單
• 如果消息消費(fèi)不過(guò)來(lái),可以設(shè)置concurrency="8" 8個(gè)消費(fèi)者,那么消費(fèi)消息的速度就會(huì)加快,不會(huì)產(chǎn)生消息的堆積
③ 告知前臺(tái)頁(yè)面秒殺結(jié)果
創(chuàng)建訂單成功或者失敗后,都把秒殺結(jié)果放入到redis中;
前臺(tái)頁(yè)面采用ajax輪詢(xún)方式查詢(xún)r(jià)edis獲取最終秒殺結(jié)果,給用戶提示。