分佈式秒殺系統
運行前一定要看文檔說明:https://gitee.com/52itstyle/spring-boot-seckill/wikis
開發環境
JDK 1.7、Maven、Mysql、Eclipse、SpringBoot 1.5.10、zookeeper 3.4.6、kafka_2.11、redis-2.8.4、curator-2.10.0
啟動說明
- 啟動前 請配置 application.properties 中相關 redis、zk 以及 kafka 相關地址,建議在Linux 下安裝使用。
- 數據庫腳本位於 src/main/resource/sql 下面,啟動前請自行導入。
- 配置完成,運行 Application 中的 main 方法,訪問 http://localhost:8080/seckill/swagger-ui.html 進行 API 測試。
- 秒殺商品頁:http://localhost:8080/seckill ,部分功能待完成。
- 本測試案例單純為了學習,某些案例並不適用於生產環境,大家根據所需自行調整。
測試入口
http://localhost:8080/seckill/swagger-ui.html
項目截圖
秒殺架構
架構層級
- 一般商家在做活動的時候,經常會遇到各種不懷好意的 DDOS 攻擊(利用無辜的吃瓜群眾奪取資源),導致真正的我們無法獲得服務!所以說高防 IP 還是很有必要的。
- 搞活動就意味著人多,接入 SLB,對多臺雲服務器進行流量分發,可以通過流量分發擴展應用系統對外的服務能力,通過消除單點故障提升應用系統的可用性。
- 基於 SLB 價格以及靈活性考慮後面我們接入 Nginx 做限流分發,來保障後端服務的正常運行。
- 後端秒殺業務邏輯,基於 Redis 或者 Zookeeper 分佈式鎖,Kafka 或者 Redis 做消息隊列,DRDS 數據庫中間件實現數據的讀寫分離。
優化思路
- 分流、分流、分流,重要的事情說三遍,再牛逼的機器也抵擋不住高級別的併發。
- 限流、限流、限流,畢竟秒殺商品有限,防刷的前提下沒有絕對的公平,根據每個服務的負載能力,設定流量極限。
- 緩存、緩存、緩存、儘量不要讓大量請求穿透到 DB 層,活動開始前商品信息可以推送至分佈式緩存。
- 異步、異步、異步,分析並識別出可以異步處理的邏輯,比如日誌,縮短系統響應時間。
- 主備、主備、主備,如果有條件做好主備容災方案也是非常有必要的(參考某年錘子的活動被攻擊)。
- 最後,為了支撐更高的併發,追求更好的性能,可以對服務器的部署模型進行優化,部分請求走正常的秒殺流程,部分請求直接返回秒殺失敗,缺點是開發部署時需要維護兩套邏輯。
分層優化
- 前端優化:活動開始前生成靜態商品頁面推送緩存和 CDN,靜態文件(JS/CSS)請求推送至文件服務器和 CDN。
- 網絡優化:如果是全國用戶,最好是 BGP 多線機房,減少網絡延遲。
- 應用服務優化:Nginx最佳配置、Tomcat 連接池優化、數據庫配置優化、數據庫連接池優化。
全鏈路壓測
- 分析需壓測業務場景涉及系統
- 協調各個壓測系統資源並搭建壓測環境
- 壓測數據隔離以及監控(響應時間、吞吐量、錯誤率等數據以圖表形式實時顯示)
- 壓測結果統計(平均響應時間、平均吞吐量等數據以圖表形式在測試結束後顯示)
- 優化單個系統性能、關聯流程以及整個業務流程
整個壓測優化過程就是一個不斷優化不斷改進的過程,事先通過測試不斷髮現問題,優化系統,避免問題,指定應急方案,才能讓系統的穩定性和性能都得到質的提升。
代碼案例
可能秒殺架構原理大家都懂,網上也有不少實現方式,但大多都是文字的描述,告訴你如何如何,什麼加鎖、緩存、隊列之類。但很少全面有的案例告訴你如何去做,既然是從0到1,希望以下代碼案例可以幫助到你。當然最終落實到生產,還有很長的路要走,要根據自己的業務進行編碼,實施並部署。
你將會在代碼案例中學到以下知識:
- 如何搭建 SpringBoot 微服務
- ThreadPoolExecutor 線程池的使用
- ReentrantLock 和 Synchronized 的使用場景
- 數據庫鎖機制(悲觀鎖、樂觀鎖)
- 分佈式鎖(RedissLock、Zookeeper)
- 進程內消息隊列(LinkedBlockingQueue、ArrayBlockingQueue、ConcurrentLinkedQueue)
- 分佈式消息隊列(Redis、Kafka)
- AOP 實現切面鎖
- Disruptor 高效隊列
- 商品詳情頁靜態化
單機
分佈式鎖應該具備哪些條件
- 在分佈式系統環境下,一個方法在同一時間只能被一個機器的一個線程執行;
- 高可用的獲取鎖與釋放鎖;
- 高性能的獲取鎖與釋放鎖;
- 具備可重入特性;
- 具備鎖失效機制,防止死鎖;
- 具備非阻塞鎖特性,即沒有獲取到鎖將直接返回獲取鎖失敗。
分佈式鎖
- 基於數據庫實現分佈式鎖;
- 基於緩存(Redis等)實現分佈式鎖;
- 基於 Zookeeper 實現分佈式鎖;
思考改進
- 如何防止單個用戶重複秒殺下單?
- 如何防止惡意調用秒殺接口?
- 如果用戶秒殺成功,一直不支付該怎麼辦?
- 消息隊列處理完成後,如果異步通知給用戶秒殺成功?
- 如何保障 Redis、Zookeeper 、Kafka 服務的正常運行(高可用)?
- 高併發下秒殺業務如何做到不影響其他業務(隔離性)?
項目地址
https://gitee.com/52itstyle/spring-boot-seckill
閱讀更多 struggledhard 的文章