日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

教你从0到1搭建秒杀系统-防超卖

發布時間:2025/3/20 windows 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 教你从0到1搭建秒杀系统-防超卖 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

各位讀者好,最近筆者學了很多東西,其實都想跟大家進行分享,奈何需要將所學習的知識整理出來需要耗費大量的時間,包括總結,或各種圖形以及寫代碼示例,所以可能更新的速度會比較慢。但大家放心,只要有時間我就會將自己學習的內容總結出來供大家一起學習討論,有總結的不對的地方大家隨時都可以批評指正,畢竟我說的也不全都是對的,希望大家耐心等待。如果你喜歡讀者的內容,可以點個關注時刻了解我的動態,同時也歡迎各位小伙伴轉發和分享。

前期概述

最近想就秒殺系統做一個梳理和總結,從0到1搭建一個簡易的秒殺系統,說實在的,也就經常會聽到秒殺系統,筆者還沒有真正的自己去搭建過一個秒殺系統,相信很多人跟我一樣。所以為了不只是停在聽說階段,我們說干就干,自己搭建一個建議的秒殺系統。我會在里面講解那些需要注意的地方以及涉及秒殺系統我們需要注意的問題,幫助大家快速了解秒殺系統的難點。同時后期也會將書寫的代碼給出來鏈接,供大家下載,代碼我會盡量精簡干練,供大家學習參考,并且依據參考可以迅速上手實際的項目,后期想要增加更多的功能也可以直接在項目上進行更改即可。
我會分幾個階段進行講解,盡量做到通俗易懂,以下是我的規劃內容(大家看的時候注意順序):

  • 教你從0到1搭建秒殺系統-防超賣.
  • 教你從0到1搭建秒殺系統-限流.
  • 教你從0到1搭建秒殺系統-搶購接口隱藏 與單用戶限制頻率.
  • 教你從0到1搭建秒殺系統-緩存與數據庫雙寫一致.
  • 教你從0到1搭建秒殺系統-Canal快速入門(番外篇).
  • 教你從0到1搭建秒殺系統-訂單異步處理.

秒殺系統簡介

本文要講的就是第一個問題:防超賣。在進行正式問題開始分析之前,我們還是啰嗦的簡單介紹一下什么是秒殺系統。相信其實有很多人都知道秒殺,像淘寶,京東等等這些里面的商戶一到節日,像什么雙11,雙12都會整一些活動,免不了有秒殺的活動,在特定的時間范圍進行搶購,平時需要幾百的東西可能這會只要幾十塊錢。其實秒殺系統真的有好多,網上對他更專業的定義也有很多,我在這里就只是簡單介紹一下,其他的我就不贅述,畢竟這不是
我們要講解的重點。我們可以將秒殺系統歸屬為一些場景:

  • 電商搶購限量的商品
  • 12306春節搶票

這些每一個功能都可以叫做秒殺系統。作為秒殺系統,用戶在進行操作了以后,大家有沒有想過最終是怎么秒殺成功或者秒殺失敗的呢?可能有的人會有這樣的疑惑,在這里不管你是想要設計秒殺系統的人還是想要搞清楚你作為買家最終是怎么成功秒殺或者失敗的,相信你看了這幾篇文章以后都可以說出個所以然來。這整體的處理邏輯可以抽象成以下幾個步驟:

  • 用戶選定商品下單
  • 校驗庫存
  • 扣庫存
  • 創建用戶訂單
  • 用戶支付等
  • 后續步驟…

我說的只是一種秒殺系統的設計方案,其實對于不同的場景,有的公司設計的秒殺系統可能步驟有所不同,有的可能最終才會扣庫存。其實不管怎么操作,這些基本的步驟都是需要的,在這里我就以我上面寫出的步驟邏輯進行講解。
也許你看到這里有一個疑惑,這整體就是個用戶買商品的流程而已啊,為啥要說它是個專門的系統呢?如果你的項目流量非常小,完全不用擔心有并發的購買請求,那么做這樣一個系統的確意義不大。但如果你的系統要像12306那樣,接受高并發訪問和下單的考驗,那么你就需要一套完整的流程保護措施,來保證你系統在用戶流量高峰期不會被搞掛了。

防超賣

好了,廢話不多說,我們接下來從防止超賣開始直接搭建項目進行實際操作。這里只是搭建簡易的秒殺系統,我們采用最傳統的Spring MVC+Mybaits的結構。

建立數據庫表結構

說了是簡易的秒殺系統,所以我們先來張最最最簡易的結構表,等未來我們需要解決更多的系統問題,再擴展表結構。我們定義兩張表,一張庫存表stock,一張訂單表stock_order,相關SQL如下:

-- ---------------------------- -- Table structure for stock -- ---------------------------- DROP TABLE IF EXISTS `stock`; CREATE TABLE `stock` (`id` int(11) unsigned NOT NULL AUTO_INCREMENT,`name` varchar(50) NOT NULL DEFAULT '' COMMENT '名稱',`count` int(11) NOT NULL COMMENT '庫存',`sale` int(11) NOT NULL COMMENT '已售',`version` int(11) NOT NULL COMMENT '樂觀鎖,版本號',PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;-- ---------------------------- -- Table structure for stock_order -- ---------------------------- DROP TABLE IF EXISTS `stock_order`; CREATE TABLE `stock_order` (`id` int(11) unsigned NOT NULL AUTO_INCREMENT,`sid` int(11) NOT NULL COMMENT '庫存ID',`name` varchar(30) NOT NULL DEFAULT '' COMMENT '商品名稱',`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '創建時間',PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

項目結構

怎么創建一個項目我這里就不一步步帶大家去創建了,這里給大家展示一下項目的整體結構圖:

典型的MCV模式。

項目代碼

Controller層代碼,提供一個HTTP接口,參數為商品的Id:

@RequestMapping("/createWrongOrder/{sid}")@ResponseBodypublic String createWrongOrder(@PathVariable int sid) {int id = 0;try {id = orderService.createWrongOrder(sid);LOGGER.info("創建訂單id: [{}]", id);} catch (Exception e) {LOGGER.error("Exception", e);}return String.valueOf(id);}

Service層代碼如下:

@Override public int createWrongOrder(int sid) throws Exception {//校驗庫存Stock stock = checkStock(sid);//扣庫存saleStock(stock);//創建訂單int id = createOrder(stock);return id; }private Stock checkStock(int sid) {Stock stock = stockService.getStockById(sid);if (stock.getSale().equals(stock.getCount())) {throw new RuntimeException("庫存不足");}return stock; }private int saleStock(Stock stock) {stock.setSale(stock.getSale() + 1);return stockService.updateStockById(stock); }private int createOrder(Stock stock) {StockOrder order = new StockOrder();order.setSid(stock.getId());order.setName(stock.getName());int id = orderMapper.insertSelective(order);return id; }

這里提供了三個方法:校驗庫存,扣庫存和創建訂單。

接口測試

我們通過JMeter(https://jmeter.apache.org/) 這個并發請求工具來模擬大量用戶同時請求購買接口的場景。我們在表里添加一個Iphone,庫存100。在JMeter里啟動1000個線程,無延遲同時訪問接口,模擬1000個人,搶購100個產品的場景。點擊啟動:

最后執行完以后,我們查詢數據如下:

賣出了56個,庫存減少了56個,但是每個請求都處理了,創建了1000個訂單。這顯然是不對的。我們需要的是賣出100個,不多也不少才能保證我們的收益。由此看來之前的設計是有問題的。既然沒有賣出去那么多就不應該創建那么多的訂單。

為了解決上面的超賣問題,我們可以在Service層給更新表添加一個事務,這樣每個線程更新請求的時候都會先去鎖表的這一行(悲觀鎖),更新完庫存后再釋放鎖。可這樣就太慢了。我們需要樂觀鎖,個最簡單的辦法就是,給每個商品庫存一個版本號version字段。我們Controller層修改代碼如下:

/*** 樂觀鎖更新庫存* @param sid* @return*/ @RequestMapping("/createOptimisticOrder/{sid}") @ResponseBody public String createOptimisticOrder(@PathVariable int sid) {int id;try {id = orderService.createOptimisticOrder(sid);LOGGER.info("購買成功,剩余庫存為: [{}]", id);} catch (Exception e) {LOGGER.error("購買失敗:[{}]", e.getMessage());return "購買失敗,庫存不足";}return String.format("購買成功,剩余庫存為:%d", id); }

Service層代碼更新如下:

@Override public int createOptimisticOrder(int sid) throws Exception {//校驗庫存Stock stock = checkStock(sid);//樂觀鎖更新庫存saleStockOptimistic(stock);//創建訂單int id = createOrder(stock);return stock.getCount() - (stock.getSale()+1); }private void saleStockOptimistic(Stock stock) {LOGGER.info("查詢數據庫,嘗試更新庫存");int count = stockService.updateStockByOptimistic(stock);if (count == 0){throw new RuntimeException("并發更新庫存失敗,version不匹配") ;} }

Mapper中updateByOptimistic方法的代碼如下:

<update id="updateByOptimistic" parameterType="cn.monitor4all.miaoshadao.dao.Stock">update stock<set>sale = sale + 1,version = version + 1,</set>WHERE id = #{id,jdbcType=INTEGER}AND version = #{version,jdbcType=INTEGER}</update>

我們在實際減庫存的SQL操作中,首先判斷version是否是我們查詢庫存時候的version,如果是,扣減庫存,成功搶購。如果發現version變了,則不更新數據庫,返回搶購失敗。

修改之后,我們跟之前一樣再重新發起請求(首先清空之前的數據,將庫存格式化重新設置為100,賣出為0):


可以看到,最終賣出去了45個,version更新為了45,同時創建了45個訂單,此時沒有超賣,不會創建多余的訂單了。


由于并發訪問的原因,很多線程更新庫存失敗了,所以在我們這種設計下,1000個人真要是同時發起購買,只有39個幸運兒能夠買到東西,我們雖然防止了超賣。但是實際上需要賣出100個商品,那剩余的沒有賣出去的話就會造成利益的減少,這樣也是不可以的。那么怎么保證在不超賣的同時還可以賣出給定數量的商品呢?我們在下一篇文章中跟大家講解。

猜你感興趣
教你從0到1搭建秒殺系統-防超賣
教你從0到1搭建秒殺系統-限流
教你從0到1搭建秒殺系統-搶購接口隱藏與單用戶限制頻率
教你從0到1搭建秒殺系統-緩存與數據庫雙寫一致
教你從0到1搭建秒殺系統-Canal快速入門(番外篇)
教你從0到1搭建秒殺系統-訂單異步處理

更多文章請點擊:更多…

參考文章:
https://cloud.tencent.com/developer/article/148805
https://juejin.im/post/5dd09f5af265da0be72aacbd
https://crossoverjie.top/%2F2018%2F05%2F07%2Fssm%2FSSM18-seconds-kill%2F

總結

以上是生活随笔為你收集整理的教你从0到1搭建秒杀系统-防超卖的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。