秒殺系統是一個併發量要求高、負載均衡要求高的、業務場景簡單可是邏輯稍微複雜的系統,因此常常會做爲面試高級後端開發的面試題。主要考察的就是對問題的拆解、分析、解決,以及架構設計的能力。前端
服務端是一個潛在的考察點,仍是有不少問題須要解決的。有些網上給出的設計方案沒有對這塊作詳細考慮。mysql
客戶端限流(在瀏覽器上行不通)web
客戶端作必定控制來限流(好比機率),防止刷單,減小成功次數,顯示在排隊,實際上沒髮網絡請求面試
前端展現redis
秒殺按鈕展現要有個定時器,涉及到先後端時鐘同步的問題sql
校對時間差後端
獲取服務端時間,客戶端時間 - 服務端時間,比較獲得差值,用這種方法來同步。然而注意到網絡是有開銷的,這個開銷須要想辦法消除。不然這種毫秒級甚至秒級的時間差,會影響到秒殺的公平性。瀏覽器
若是這個同步是很長時間以前同步的呢,可能時間過了好久後已經相差較多了。緩存
若是客戶修改系統時間怎麼辦服務器
這一層要考慮限流問題,以及防止惡意刷量的問題。首先限流要儘可能在上層去作,以最大程度減小後端系統的壓力。其次,要避免用戶找到url,不停的大量發送網絡請求,或者在活動前就發送,這樣也是有問題的。
限流
這屬於分佈式限流,通常採用 redis 來作限流,能夠用令牌桶來作
防止提早刷 url
這個能夠在服務端根據系統時間來決定要不要處理,也能夠用一個隨機的網址來保證沒法模擬 url 請求(這個點還比較模糊)
並且這裏涉及到服務端各服務器的時鐘同步
同一個 url
這裏能夠用 redis 記錄或者本地記錄來進行計數過濾,保證用戶每秒發送請求響應次數不超過一個閾值
悲觀鎖
性能比較差
樂觀錯
性能好些
緩存
緩存來保存庫存量,減小訪問 mysql 帶來的併發,用 redis 能夠作到
可是若是在拿到資格後出現問題,怎麼辦?在緩存裏已經被減掉了,這時須要歸還資格,不然賣出的數就會少,這個錯誤可能會出如今生單,訂單入庫的階段,直到入庫,這個資格才能算做完全被消費掉
mysql 更合適,有惟一鍵的限制,hbase 存放海量數據
同步仍是異步的問題
同步
好處,等待結果寫入庫裏,徹底閉環
異步
可能會寫入失敗,丟失訂單信息,由於訂單詳情是要儘快展現給用戶的,因此一旦失敗,該取消此次秒殺的結果,仍是繼續認爲成功,是比較棘手的問題。異步出錯了,可能能夠修復,可是也可能會一直出錯,重試無效。這種應該歸還,而後把結果通知給用戶。若是異步默認生單成功,可是怎麼也寫不進去,那就會有問題了。(這塊每太想清楚)
先說說異步作法
交由本地線程池處理
佔用 service 層資源
發送 kafka
減小了 service 層資源佔用,可是要保證 kafka 可靠,這裏須要保證 有副本,ack -> ALL,replica 設置>1
如何保證同一個用戶只能下一個單
由於資源被佔用後,後續不必定生單成功,因此若是資源沒了,不該該直接展現秒殺結束
server 端時間同步