Java架構師筆記-電商系統設計之——秒殺系統設計

Java 設計 Redis MySQL 電子商務 數據庫 jQuery 技術 Java架構師筆記 2019-05-28

業務場景

在電商系統中,商家為了增加營收,經常會推出一些優惠刺激客戶消費,其中"秒殺"就是最常用的一種,參與秒殺的商品,往往都比正常銷售價格低很多很多,所以秒殺活動會吸引來大量的用戶參與進來。但是,電商系統如果不針對這一種場景去做性能優化,當大量請求在一瞬間進來服務器的時候,就有可能導致系統崩潰,甚至根本無法參與本次秒殺活動。

這種情況不僅對用戶體驗不友好,而且對商家的損失也是非常大的,今天我要講的就是針對秒殺業務場景的系統設計。

注:本文案例僅針對我們的關注點開發,即高併發處理、正確高效減庫存,其餘部分只做簡單處理,能滿足業務正常流程即可。

實現目標

  • 商品頁面展示秒殺開啟倒計時。
  • 高併發場景下,用戶下單正常,數據持久化到數據庫。
  • 秒殺地址只有在秒殺開啟的時候才能拿到。
  • 商品庫存不能超賣。

設計思路

  • 參與秒殺的商品信息,全部放在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 異步定時同步庫存

系統架構

Java架構師筆記-電商系統設計之——秒殺系統設計

時序圖

Java架構師筆記-電商系統設計之——秒殺系統設計

秒殺界面

Java架構師筆記-電商系統設計之——秒殺系統設計

前端核心邏輯

為商品綁定計時器

Java架構師筆記-電商系統設計之——秒殺系統設計

利用的是jq的countdown計時插件。當未開啟秒殺的商品倒計時結束後,即開啟秒殺,調用獲取秒殺地址的方法seckillUrl(id)。當已經開始秒殺的商品倒計時結束後,即秒殺結束,置灰秒殺按鈕。

countdown插件:https://cdn.bootcss.com/jquery.countdown/2.2.0/jquery.countdown.min.js

獲取秒殺地址

Java架構師筆記-電商系統設計之——秒殺系統設計

調用獲取秒殺地址的方法,通過調用後臺接口獲取秒殺地址。如果用戶停留在秒殺頁面過久,計時插件會出現時間偏移的情況,也就是前後端的時間不一致了。這個時候就需要後端校驗秒殺時間,如果秒殺還未開啟,則返回系統時間和秒殺開啟時間,然後再更新前端計時插件的時間,等計時結束,重新觸發獲取秒殺地址。如果秒殺已開啟,則直接返回秒殺地址的md5,最後前端拼接成秒殺地址。

執行秒殺方法

Java架構師筆記-電商系統設計之——秒殺系統設計

執行秒殺中,也會存在時間偏移的現象,所以每一次調用秒殺接口的時候,也需要後端校驗秒殺狀態,如果秒殺未開啟的話要返回服務器時間和秒殺開啟時間,讓前端更新計時器時間。

後端核心邏輯

秒殺總開關接口實現

Java架構師筆記-電商系統設計之——秒殺系統設計

設置一個秒殺活動的總開關,開啟的時候將數據庫中所有參與秒殺的商品全部緩存至redis,之後頁面獲取的數據全部從redis獲取,每個商品的庫存也單獨使用一個list結構存儲,存儲的value隨意,行數等於庫存數即可,一行代表一個庫存。關閉秒殺活動即把redis中所有緩存清空即可。

獲取秒殺地址接口實現

Java架構師筆記-電商系統設計之——秒殺系統設計

Java架構師筆記-電商系統設計之——秒殺系統設計

先校驗商品的秒殺狀態是否為秒殺中,如果是則返回秒殺地址md5,秒殺狀態為未開始,則返回服務器時間和秒殺時間。秒殺狀態為已結束則不返回秒殺地址md5。加密規則可以自己定,一般只要滿足不可逆,秒殺未開啟獲取不到即可。

執行秒殺接口實現

Java架構師筆記-電商系統設計之——秒殺系統設計

Java架構師筆記-電商系統設計之——秒殺系統設計

Java架構師筆記-電商系統設計之——秒殺系統設計

秒殺接口的校驗邏輯跟獲取秒殺地址MD5的邏輯相似,只有在秒殺時間範圍內才能進行後續邏輯。減庫存直接使用redisTemplate.opsForList().leftPop(...)方法即可完成redis減庫存。返回的對象不為null則代表減庫存成功。然後可以根據業務需求,記錄購買明細或相關操作,最好是異步處理,讓秒殺接口儘可能快處理完一次請求。

注:一次秒殺同步更新一次mysql庫存是不可取的。當請求量增加的速度大於mysql處理update的速度時,即使是異步處理,mysql的行級鎖依然會拖死數據庫。本案例採取的方式是,秒殺開啟後,定時一分鐘獲取一次redis庫存同步到mysql。

結語

真正影響秒殺性能的因素還有很多,例如異地機房的網絡延遲,GC消耗,業務層的事務控制等等。需要優化的地方也不僅僅是文中所提及幾個點,本文介紹的秒殺系統只是一個雛形,重點在於讓大家瞭解秒殺系統的整體結構。

以上就是電商系統設計之——秒殺系統設計方案,分享給大家,希望大家知道什麼電商系統設計之——秒殺系統設計,覺得收穫的話可以點個關注收藏轉發一波喔,謝謝大佬們支持!

多寫多敲代碼,好的代碼與紮實的基礎知識一定是實踐出來的

推薦:Java高級開發,Java架構師/大型互聯網架構進階直播

地址:http://t.cn/AiKfJ6Zx

(複製鏈接到瀏覽器即可)

最後,每一位讀到這裡的網友,感謝你們能耐心地看完。希望在成為一名更優秀的Java程序員的道路上,我們可以一起學習、一起進步!都能贏取白富美,走向架構師的人生巔峰!

相關推薦

推薦中...