目錄
基於spring boot高性能高併發秒殺系統方案及優化(第一部分:初步方案+分佈式會話+參數效驗解析)
項目源碼:https://github.com/yingyingqiqi/flash
這是電商系統的一個模塊,主要涉及秒殺這個應用場景,但是,裏面的知識卻超越了秒殺,涉及到高併發、高性能的系統構建(緩存+異步+限流)
閒扯:這篇文章是對慕課網“Java秒殺系統方案優化 高性能高併發實戰”課程的學習總結,以及自己的一些看法和改良,很久之前看的課程了,現在二刷,並加上一些示意圖,方便自己或者他人理解秒殺涉及到的技術。
文章整體思路介紹:
1.完成一些基礎的工具類開發,分佈式會話、原生redis的API集成、參數的效驗及解析、秒殺的初步構想。
2.秒殺的優化,各種加緩存、異步化、防刷限流。
3.這篇文章不講代碼的實現,主要講思路,給出示意圖,方便理解。
技術棧:spring+ spring boot+ mybatis+ +redis+ rabbitmq+ 前端技術知識
秒殺未優化前示意圖
1.一句話講清楚瓶頸:無緣無故,時時刻刻請求數據庫,數據庫併發是很小的。
頁面級高併發秒殺優化(Redis緩存+靜態化分離)
使用不同層級和粒度的緩存對系統做優化改造,比如:對服務端手動渲染商品列表做頁面緩存,對商品詳情靜態化來利用客戶端瀏覽器的緩存,對熱點數據做對象級的緩存
重點:手動渲染商品列表做頁面緩存
1.第一部分已經介紹了,頁面時通過thymeleaf構建視圖(你可以理解爲jsp),thymeleaf是spring推薦使用
2.手動渲染視圖,將渲染結果存入redis中。用戶請求時,直接返回redis中的html
3.當頁面需要顯示用戶信息的時候,這種方式是不適合的。
重點:頁面靜態化(利用瀏覽器的緩存) 即前後端分離
1.頁面靜態化,也稱前後端分離,服務端配置,用戶請求,服務器響應時,不返回數據,只返回html純頁面。
2.此純html頁面,通過Ajax向服務端第二次請求,獲取所需數據。
非編程的優化,靜態資源優化
重點:秒殺接口第一次優化
1.此次優化,主要解決超賣問題,並沒有涉及很深入的優化
服務級高併發秒殺優化(RabbitMQ+接口優化)
將通過預減庫存減少透穿到DB的請求,通過異步處理和排隊機制緩解數據庫的壓力,降低應用接口負載,主要包括內存標記,Redis做庫存預判,消息隊列異步寫庫,秒殺接口優化。
重點:秒殺接口第二次優化
1.系統初始化,把商品庫存數量加載到redis,建立內存標記(hashMap),減少redis訪問(網絡請求延時)。
2.redis預減庫存,庫存不足,直接返回失敗,減少用戶請求向下訪問。
3.建立消息隊列,請求入隊,秒殺實際操作延遲執行,即異步寫庫,直接返回提示(排隊等待)。
4.請求出隊,減少庫存,生成訂單,訂單存入redis中,等待輪詢結果。
5.前端發送Ajax請求輪詢秒殺結果。(類似12306買票,排隊中)
圖形驗證碼及惡意防刷
隱藏秒殺地址,實現圖形驗證碼,接口限流防刷,列表頁和詳情頁防刷,秒殺操作防刷,驗證碼防刷等。
重點:接口地址隱藏
1.第一次請求服務端獲取一串隨機字符(每個用戶唯一60秒失效),url拼上字符纔是實際地址。
2.接口地址的隱藏,類似接口防止重放攻擊,實際地址中帶入一串字符,請求到達服務端,驗證字符。
3.可以設計的再複雜一點,隨機字符只可以使用一次,請求第一次到達後失效。
重點:接口防刷限流(同一ip一秒鐘訪問多少次)
1.使用springMVC的HandlerInterceptorAdapter攔截器,實現抽象類preHandler方法
2.這裏優化第一部分的參數解析器,對於獲取user用戶信息的步驟。利用ThreadLocal (線程安全的容器)存儲user用戶信息。
3.通過攔截器,攔截使用AccessLimit註解的方法,並獲取註解的數據,檢查訪問次數是否超出限制,沒超限制放行此方法。
秒殺壓測-Jmeter壓力測試
壓力測試神器-JMeter,由於單機部署,mysql,redis,jdk等都在一部機器上。大致壓測結果爲(5000個用戶10次請求):
QPS 商品列表 秒殺接口
優化前 920 950
優化後 2540 2103