秒殺的基本講解
秒殺后端的詳細簡介
需要了解的問題
面試時可能會問的問題
基本講解
1、秒殺開始前,秒殺按鈕灰掉為“未開始”,不可點擊。
2、URL在活動開始前不可露出或者生效,否則容易被使用工具繞過瀏覽器提前下單。導致活動還未開始,已經開始下單這個大黑洞。我們的做法是在活動開始前,通過更新JS文件露出下單的URL。
3、在秒殺進行中,秒殺按鈕才可以點擊下單。
4、秒殺產品的介紹,詳情,參數等等,全部靜態化,將秒殺商品頁面緩存在CDN上(資源沒那么好其實可以放在Nginx中做動靜分離)
5、用戶點擊“下單”后,按鈕置灰,禁止用戶重復提交請求,限制用戶在60秒之內只能提交一次請求。(防止DDOS攻擊,后面有講)
6、然后就發送請求了,請求統一發送到Nginx中,Nginx中限流了,
7、Nginx限流后把請求分發到tomca的秒殺接口上面去,
8、然后到了秒殺接口上了,這個秒殺接口的項目在啟動運行的時候就把商品id和數量保存到了Redis中,
9、在做唯一性判斷,對uid進行請求計數和去重,發現發送過秒殺請求就結束秒殺
10、然后請求到達時通過要秒殺的id號到Redis中去查詢預減庫存,只要商品庫存不到0就執 行下一步,(因為Redis的操作是具有原子性所以不會出現超賣的問題),
11、如果是分布式項目下單的接口在另外的微服務中的話,就把訂單消息傳MQ,這個MQ實現了流量削峰后在以先進先出的方式進行異步下單(前期都沒操作數據庫,防止服務器壓力太大會死機的,,經過MQ之后才訪問數據庫)。。。
11、如果就在此接口下單的話就只需要調用下單接口生成訂單就好了,不需要中間插件了。
12、下單的過程中的SQL語句還使用了樂觀鎖進行操作的再次控制防止出現超賣現象,
13、秒殺結束后,秒殺按鈕灰掉為“已結束”,不可點擊。
詳細講解
前端操作
1、秒殺開始前,秒殺按鈕灰掉為“未開始”,不可點擊。
2、URL在活動開始前不可露出或者生效,否則容易被使用工具繞過瀏覽器提前下單。導致活動還未開始,已經開始下單這個大黑洞。我們的做法是在活動開始前,通過更新JS文件露出下單的URL。
3、在秒殺進行中,秒殺按鈕才可以點擊下單。
4、秒殺產品的介紹,詳情,參數等等,全部靜態化,將秒殺商品頁面緩存在CDN上(資源沒那么好其實可以放在Nginx中做動靜分離)
CDN服務器就是內容分發網絡,把資源內容放在了全國各地的各服務器,通過中心平台的負載均衡、內容分發、調度等功能模塊,使用戶就近獲取所需內容。(一般都是到阿里雲買CDN服務器)
5、用戶點擊“下單”后,按鈕置灰,禁止用戶重復提交請求,限制用戶在60秒之內只能提交一次請求。(防止DDOS攻擊,后面有講)
6、然后就發送請求了,請求統一發送到Nginx中
后端操作
1、Nginx收到前端的請求后,在進行限流操作后才把前端秒殺的請求發送到Tomcat服務器上的秒殺接口上《=======》也就是說:這Nginx轉發請求到tomcat的層到途中:Nginx限制用戶的重復提交,使用了限流在某一時間段內只允許用戶提交一次請求到秒殺接口(重點)
為什么要Nginx限流:Nginx限流就是限制用戶請求速度,防止服務器受不了(防止DDOS攻擊,后面有講)
Nginx限流有3種
1、限制訪問頻率(正常流量)
2、限制訪問頻率(突發流量)
3、限制並發連接數
我這只寫了最平常的一種,限制訪問頻率(正常流量):限制一個用戶發送的請求,我Nginx多久接收一個,(例如:一個用戶在一分鍾發1000個請求對服務器的壓力肯定很大,我如果在Nginx定義了一個人一分鍾一個請求的限流的話,我Nginx就是只接收一個,其他的都不要),這也叫做漏桶流:
圖片偷得哈,別在意
重點:Nginx配置的限流代碼:
2、然后到了秒殺接口上了,這個秒殺接口的項目在啟動運行的時候就把商品id和數量保存到了 Redis中,
秒殺項目啟動時的操作,把商品id和數量保存到了 Redis中,(我們考Redis來解壓力,防止服務器和數MySql受不了)
3、項目運行流程先做唯一性判斷,對uid進行請求計數和去重,發現以經發送過秒殺請求就結束秒殺。
萬一人家不通過Nginx進來秒殺怎么辦,直接訪問秒殺接口(所以需要再次判斷Uid)
再次(防止DDOS攻擊)
4、然后請求到達時通過要秒殺的id號到Redis中去查詢預減庫存,只要商品庫存不到0就執 行下一步,(因為Redis的操作是具有原子性所以不會出現超賣的問題),(重點)
關鍵的decr方法(redis中的原子遞減,根據key減value值)
decr key
將指定key的value原子性遞減1,就相當於java中的–i。 如果該key不存在,其 初始值為0,在decr之后其值為-1。如果value的值不能轉成整型,如helllo,該操作將 執行失敗並返回相應的錯誤信息。
代碼:
5、然后在把訂單消息傳入MQ,MQ去通知下單接口生成訂單,這個MQ實現了流量削峰后在以先進先出的方式進行異步下 單(前期都沒操作數據庫,防止服務器壓力太大會死機的,,經過MQ之后才訪問數據庫)。。。注意:(可以不需要此MQ,此MQ只是在分布式項目中需要,就是下單接口在另外的項目就需要,要此MQ還不好,因為中間插件掛了秒殺系統也掛了,其實可以直接調用下單的方法了)
5、如果就在此接口下單的話就只需要調用下單接口生成訂單就好了,不需要中間插件了。
6、下單的過程中的SQL語句還使用了樂觀鎖進行操作的再次控制防止出現超賣現象,(其實可以不需要,只是保證以下,其實可以直接生成下單的訂單了)
樂觀鎖的標記值判斷就是把redis中返回預減后的的值去和數據庫的庫存去判斷,達到一個防止超賣的現象
7、到此秒殺結束后,秒殺按鈕灰掉為“已結束”,不可點擊。
需要了解的問題
1、什么是漏桶流,
NGINX限流使用漏桶算法(leaky bucket algorithm),該算法廣泛應用於通信和基於包交換計算機網絡中,用來處理當帶寬被限制時的突發情況。和一個從上面進水,從下面漏水的桶的原理很相似;如果進水的速率大於漏水的速率,這個桶就會發生溢出。
在請求處理過程中,水代表從客戶端來的請求,而桶代表了一個隊列,請求在該隊列中依據先進先出(FIFO)算法等待被處理。漏的水代表請求離開緩沖區並被服務器處理,溢出代表了請求被丟棄並且永不被服務。
2、什么是MQ的削峰
MQ的削峰也和漏桶流有點相似道理,只不過他是一個永遠不會漏的桶,請求在多沒關系,我先接着,我慢慢來,不管你多少請求我都按照我的速度慢慢來,保證消息不丟失。
3、Tomcat最多支持並發多少用戶?
Tomcat 默認配置的最大請求數是 150,也就是說同時支持 150 個並發,當然了,也可以將其改大。
當某個應用擁有 250 個以上並發的時候,應考慮應用服務器的集群。
具體能承載多少並發,需要看硬件的配置,CPU 越多性能越高,分配給 JVM 的內存越多性能也就越高,但也會加重 GC 的負擔。
操作系統對於進程中的線程數有一定的限制:
Windows 每個進程中的線程數不允許超過 2000
Linux 每個進程中的線程數不允許超過 1000
另外,在 Java 中每開啟一個線程需要耗用 1MB 的 JVM 內存空間用於作為線程棧之用。
Tomcat的最大並發數是可以配置的,實際運用中,最大並發數與硬件性能和CPU數量都有很大關系的。更好的硬件,更多的處理器都會使Tomcat支持更多的並發。
4、Nginx支持多少並發
單個Nginx並發盡量不要超過2萬,如果超過了就要做集群了,雖然官方監測能支持5萬並發
5、MySql最大的並發
MySql最大的並發量500-1000,好一點的服務可以支持1000-2000,超過了還是要集群
面試可能會問的問題
1、庫存超賣
只有10個庫存,但是一秒鍾有1k個訂單,怎么能不超賣呢?
核心思想就是保證庫存遞減是原子性操作,10–返回9,9–返回8,8–返回7。
而不能是讀取出來庫存10,10-1=9再更新回去。因為這個讀取和更新是並發執行的,很可能就會有1k個訂單都成功了,而庫存實際只有10。
那么,怎么保證原子性操作呢?
1 .數據庫判斷庫存不能小於0(我們使用到了,比他吊一點,樂觀鎖)
update product set left_num=left_num-1 where left_num>0;
2.分布式鎖(我們沒有使用)
用redis來做一個分布式鎖,reids->setnx(‘lock’, 1) 設置一個鎖,程序執行完成再del這個鎖。
鎖定的過程,不利於並發執行,大家都在等待鎖解開,不建議使用。
3 .消息隊列(我們使用了)
將訂單請求全部放入消息隊列,然后另外一個后台程序一個個處理隊列中的訂單請求。
並發不受影響,但是用戶等待的時間較長,進入隊列的訂單也會很多,體驗上並不好,也不建
4 redis遞減(我們使用了,decr方法就是原子性遞減)
通過 redis的:decr(‘key’)方法 以原子性的方式得到遞減之后的庫存數。
性能方面很好,同時體驗上也很好
2、集群怎么來規划
前端服務器不用管,集群的數量不受影響。
redis的性能可以達到每秒幾萬次響應,所以一個集群的規模,也就是redis服務可以承載的數量。
比如:一台前端服務器是1-2k的qps(有庫存時),那么10台+1台redis就可以是一個獨立的集群,可以支撐1-2w每秒訂單量。
10個上述的集群就可以做到一秒鍾處理10w~20w的有效訂單。
如果秒殺活動的庫存量在1w以內,預計參與的人數在百萬左右,那么有一個集群也就可以搞定。
如果秒殺參與的人數超過千萬,那么就要用到不止一個集群了。
3、多個集群的數據怎么保持一致性啊
不要做多集群的數據同步,而是用散列,每個集群的數據是獨立存在的。
假設,有10個商品,每個商品有1w庫存,規划用10個集群,那么每個集群有10個商品,每個商品是1k庫存。
每個集群只需要負責把自己的庫存賣掉即可,至於說,會不會有用戶知道有10個集群,然后每個集群都去搶。
這種情況就不要用程序來處理了,利用運營規則,活動結束后匯總訂單的時候再去處理就好了。
如果擔心散列的不合理,比如:某個集群用戶訪問量特別少,那么可以引入一個中控服務,來監控各個集群的庫存,然后再做平衡。
4、機器人搶購怎么辦
沒什么太好的辦法,類似DDOS攻擊,只能是讓自身更強大才是王道。
運營策略上,可以嚴格控制用戶注冊,必須登錄,提交訂單的時候引入圖像驗證碼,問答,交互式驗證等。
5.你的秒殺系統可以做到多少並發量。
前台我沒做,
我就光說后台吧,使用JMeter測試的吧
首先Nginx
1000個並發的秒殺,倆台台tomcat,幾秒就搞定,具體的我不記得了,Jm測試工具是時間戳顯示
假如做10000並發的秒殺就要很多台服務器
我就假如做10000並發的秒殺,資源是5台tomcat的話,Nginx就不怕,Nginx2萬並發隨隨便便,超過2萬並發最好使用集群
在Nginx定義限流維度,每秒1000個請求漏下去,漏到Tomcat,大概呢就是十幾二十秒秒殺完。
在說Tomcat,Tomcat可以接受150-250並發之間,超過250並發最好也使用集群
redis的性能可以達到每秒幾萬次響應,所以一個集群的規模,也就是redis服務可以承載的數量。
比如:一台前端服務器是1-2k的qps(有庫存時),那么10台+1台redis就可以是一個獨立的集群,可以支撐1-2w每秒訂單量。
最后結束!如果需要源碼就留言給我吧(o(╥﹏╥)o),都沒有人點贊,沒有人留言,難受···
————————————————
版權聲明:本文為CSDN博主「小傑要吃蛋」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/weixin_43122090/article/details/103652202