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