1. 程式人生 > >秒殺系統設計(JAVA)

秒殺系統設計(JAVA)

高併發 一、前端 1.靜態化頁面,將頁面快取在使用者的瀏覽器和CDN上 2.提交後按鈕disabled,禁止使用者重複提交 二、伺服器叢集 1.通過nginx分發請求,提前預判會產生的PV數,部署合適數量的伺服器叢集,防止其中一臺Web機器掛了,導致流量分散到其他正常工作的機器上,再導致正常的機器也掛,將整個Web系統拖垮 2.優化伺服器中介軟體如tomcat jvm優化(虛擬機器初始化時的最小記憶體,可用最大記憶體,GC模式等),併發連線優化(初始化 socket執行緒數,最大socket執行緒數等) 三、服務端層 1.秒殺業務是一個讀多寫少的場景,大部分請求是查詢請求,多使用快取對應讀的請求,增加服務端響應速度,減少CPU處理多個連線數的壓力 導致整體響應速度變慢,以及web伺服器連結數被佔滿 減庫存實現邏輯
2-1.將商品的開始時間放置在redis快取中,判斷是否到了秒殺開始時間 2-2.請求間隔是否符合正常時間(如將使用者上一次的請求時間記錄下來計算時間差) 2-3.將商品庫存剩餘數量放置到redis快取中,判斷庫存數量是否還有剩餘 2-4.有剩餘的話,獲取一個redis分散式鎖 利用redis的.setnx命令,先判斷是否存在再賦值 因為redis都是序列操作的,不存在併發問題 拿到鎖: 2-5.處理業務邏輯,如將資料放置在一個mq中,然後通過incr、incrby、decr、decrby原子操作命令控制庫存數,減少資料庫IO的開銷
  • incr遞增1並返回遞增後的結果;
  • incrby根據指定值做遞增或遞減操作並返回遞增或遞減後的結果(incrby遞增或遞減取決於傳入值的正負);
  • decr遞減1並返回遞減後的結果;
  • decrby根據指定值做遞增或遞減操作並返回遞增或遞減後的結果(decrby遞增或遞減取決於傳入值的正負);
2-6.釋放鎖,返回應答 未拿到鎖: 2-7.執行緒sleep再次嘗試拿鎖 ,多次未拿到鎖則返回使用者活動太火爆 3.資料庫層操作sql語句加上樂觀鎖做一個保護 四、防作弊 1.同一個賬號,一次性發出多個請求 部分使用者通過瀏覽器的外掛或者其他工具,在秒殺開始的時間裡,以自己的賬號,一次傳送上百甚至更多的請求。實際上,這樣的使用者破壞了秒殺和搶購的公平性。 應對方案: 1.同一賬號請求記錄時間戳標記位。(可以在redis里根據使用者ID 記錄一條資料,比如1秒後失效) 2.再次請求的時候判斷標記位是否存在,如果存在就立即打回請求。 2.多個賬號,一次性發送多個請求
例如微博中有轉發抽獎的活動,如果我們使用幾萬個“殭屍號”去混進去轉發,這樣就可以大大提升我們中獎的概率。 如果發現某個IP請求頻率很高 應對方案: 1.返回驗證碼,區分真實使用者 3. 多個賬號,不同IP傳送不同請求 黑客操作多個肉雞 應對方案: 1.活動開始前通過一些資料探勘篩選過濾殭屍號,殭屍賬號也還是有一些共同特徵的,例如賬號很可能屬於同一個號碼段甚至是連號的,活躍度不高,等級低,資料不全等等。根據這些特點,適當設定參與門檻,例如限制參與秒殺的賬號等級。 4. 火車票的搶購 高階的黃牛刷票時,在識別驗證碼的時候使用真實的人,中間搭建一個展示驗證碼圖片的中轉軟體服務,真人瀏覽圖片並填寫下真實驗證碼,返回給中轉軟體。對於這種方式,驗證碼的保護限制作用被廢除了,目前也沒有很好的解決方案。 應對方案: 1.賬號資料進行“資料探勘”,這些黃牛賬號也是有一些共同特徵的,例如經常搶票和退票,節假日異常活躍等等。將它們分析出來,再做進一步處理和甄別。