業務場景
在電商系統中,商家為了增加營收,經常會推出一些優惠刺激客戶消費,其中"秒殺"就是最常用的一種,參與秒殺的商品,往往都比正常銷售價格低很多很多,所以秒殺活動會吸引來大量的用戶參與進來。但是,電商系統如果不針對這一種場景去做性能優化,當大量請求在一瞬間進來服務器的時候,就有可能導致系統崩潰,甚至根本無法參與本次秒殺活動。
這種情況不僅對用戶體驗不友好,而且對商家的損失也是非常大的,今天我要講的就是針對秒殺業務場景的系統設計。
注:本文案例僅針對我們的關注點開發,即高併發處理、正確高效減庫存,其餘部分只做簡單處理,能滿足業務正常流程即可。
實現目標
- 商品頁面展示秒殺開啟倒計時。
- 高併發場景下,用戶下單正常,數據持久化到數據庫。
- 秒殺地址只有在秒殺開啟的時候才能拿到。
- 商品庫存不能超賣。
設計思路
- 參與秒殺的商品信息,全部放在redis緩存。
- 秒殺時間始終從後臺獲取。
- 將商品庫存使用redis的list結構存儲,一行數據即一個庫存。
- 利用redis的pop方法彈出庫存,即高效,又保證數據準確,不會超賣。
- 秒殺開啟時返回前端一個加密的MD5,由前端拼接成完整的秒殺地址。
- quartz定時將redis庫存同步更新至mysql持久化。
技術架構
- 前端:bootstrap + jquery + thymeleaf
- 後端:springboot + redis + mybatis + mysql + quartz
- bootstrap 框架作為前端頁面全局樣式
- jquery 處理頁面邏輯
- thymeleaf 作為後端數據展示模板引擎
- springboot 應用
- redis 處理熱點數據存儲,並利用其原子性操作減庫存
- mybatis 持久層框架
- mysql 數據庫
- quartz 異步定時同步庫存
系統架構
時序圖
秒殺界面
前端核心邏輯
為商品綁定計時器
利用的是jq的countdown計時插件。當未開啟秒殺的商品倒計時結束後,即開啟秒殺,調用獲取秒殺地址的方法seckillUrl(id)。當已經開始秒殺的商品倒計時結束後,即秒殺結束,置灰秒殺按鈕。
countdown插件:https://cdn.bootcss.com/jquery.countdown/2.2.0/jquery.countdown.min.js
獲取秒殺地址
調用獲取秒殺地址的方法,通過調用後臺接口獲取秒殺地址。如果用戶停留在秒殺頁面過久,計時插件會出現時間偏移的情況,也就是前後端的時間不一致了。這個時候就需要後端校驗秒殺時間,如果秒殺還未開啟,則返回系統時間和秒殺開啟時間,然後再更新前端計時插件的時間,等計時結束,重新觸發獲取秒殺地址。如果秒殺已開啟,則直接返回秒殺地址的md5,最後前端拼接成秒殺地址。
執行秒殺方法
執行秒殺中,也會存在時間偏移的現象,所以每一次調用秒殺接口的時候,也需要後端校驗秒殺狀態,如果秒殺未開啟的話要返回服務器時間和秒殺開啟時間,讓前端更新計時器時間。
後端核心邏輯
秒殺總開關接口實現
設置一個秒殺活動的總開關,開啟的時候將數據庫中所有參與秒殺的商品全部緩存至redis,之後頁面獲取的數據全部從redis獲取,每個商品的庫存也單獨使用一個list結構存儲,存儲的value隨意,行數等於庫存數即可,一行代表一個庫存。關閉秒殺活動即把redis中所有緩存清空即可。
獲取秒殺地址接口實現
先校驗商品的秒殺狀態是否為秒殺中,如果是則返回秒殺地址md5,秒殺狀態為未開始,則返回服務器時間和秒殺時間。秒殺狀態為已結束則不返回秒殺地址md5。加密規則可以自己定,一般只要滿足不可逆,秒殺未開啟獲取不到即可。
執行秒殺接口實現
秒殺接口的校驗邏輯跟獲取秒殺地址MD5的邏輯相似,只有在秒殺時間範圍內才能進行後續邏輯。減庫存直接使用redisTemplate.opsForList().leftPop(...)方法即可完成redis減庫存。返回的對象不為null則代表減庫存成功。然後可以根據業務需求,記錄購買明細或相關操作,最好是異步處理,讓秒殺接口儘可能快處理完一次請求。
注:一次秒殺同步更新一次mysql庫存是不可取的。當請求量增加的速度大於mysql處理update的速度時,即使是異步處理,mysql的行級鎖依然會拖死數據庫。本案例採取的方式是,秒殺開啟後,定時一分鐘獲取一次redis庫存同步到mysql。
結語
真正影響秒殺性能的因素還有很多,例如異地機房的網絡延遲,GC消耗,業務層的事務控制等等。需要優化的地方也不僅僅是文中所提及幾個點,本文介紹的秒殺系統只是一個雛形,重點在於讓大家瞭解秒殺系統的整體結構。
以上就是電商系統設計之——秒殺系統設計方案,分享給大家,希望大家知道什麼電商系統設計之——秒殺系統設計,覺得收穫的話可以點個關注收藏轉發一波喔,謝謝大佬們支持!
多寫多敲代碼,好的代碼與紮實的基礎知識一定是實踐出來的
推薦:Java高級開發,Java架構師/大型互聯網架構進階直播
地址:http://t.cn/AiKfJ6Zx
(複製鏈接到瀏覽器即可)
最後,每一位讀到這裡的網友,感謝你們能耐心地看完。希望在成為一名更優秀的Java程序員的道路上,我們可以一起學習、一起進步!都能贏取白富美,走向架構師的人生巔峰!