我們的秒殺請求到了tomcat之后,我整個請求到了后端,我們怎么抗住高并發
也就是讓他1s抗住10w的訂單量,該怎么做
>> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >
一般來說秒殺系統都是需要單獨部署的,因為它的并發壓力很大他跟我們正常微服務或者web系統都是需要 單獨剝離開的
這就是我們秒殺商品最簡單的代碼,假設我現在就只剩下一個庫存了.我幾十個請求同一時刻調用了查詢db的方法,呢它都查到還有一個庫存 ,都會減1 操作 意味著嚴重超賣update( product) -----> 意味著減1 操作超賣的問題如何解決 此時必然不能加sy鎖,因為加了鎖之后我們的并發就抗不到10w以上了如果要求并發不高可以加鎖我們可以利用 update stock -1 where shock > 0 利用行鎖
我其實是用數據庫來幫我們解決并發 超賣的問題
我們其實是用數據庫的樂觀鎖的方式來更新我們的e庫存 解決超賣的問題
我就不用在整個代碼邏輯上加鎖了
這樣來做性能會高一些有什么好的優化方案,讓我這個系統的并發繼續上升。
我們一般會用redis+mq
== == == == == == == == == == == == == == == == == == >> >> >> >> >> >> >> >> >> >> >> >> >
我們秒殺走緩存得方案,我們秒殺得商品庫存 提前放到緩存中 這個叫做緩存預熱然后我們真正減少db,然后我們真正減庫存的時候 不是直接db干的,db并發太低了,我們一般在緩存中扣減庫存
所以我們的秒殺系統,會提前預熱商品緩存緩存
然后我們真正做秒殺的時候,從redis查商品庫存一般mq下單,慢慢去消費。我異步創建訂單.也就是前端下單鏈路 沒有操作db的
性能很高得因為redis 的并發本身就可以支撐很高 如果用kafka 或者mq ,它得并發也很高
我前端給用戶返回一個搶購成功前端 給用戶一個緩沖 我可以每過2到3s中 往后臺發一個查詢訂單的請求
看下你這個訂單有沒有下成功 如果你沒有下成功
我繼續再重發請求 又過2到3s 再去發 當你后端mq消費完畢 被下單成功后
我這個時候再去查詢的時候 下單成功 轉到支付頁面
redis理論上每秒能抗10w的并發,但是實際上沒有 而且一般是讀的時候才可以
我們的redis是有讀有寫,也就是說redis既有查詢又有寫的時候 是支撐不了10w并發的
redis集群架構
正常用redis單節點 有單節點問題 如果用redis集群架構
我們服務端的redis集群 我們數據在redis集群中是分片存儲的比方說我線上有10個商品 這10個商品實際上是分布式在不同的redis節點上
真正的redis節點它的數據是分片存儲的
根據它的hash 分片算法
redis集群 他會幫我們把數據進行分片來存儲
我一個redis節點讀寫并發 就2w左右
假設現在我有10個商品 我按照334 的拆分
我每秒 都能抗接近10w 的并發了
redis做集群架構 讓你的所有的秒殺 活動 的商品均勻的分配在redis的節點
但是沒有呢么理想 很有可能10 個商品 按照hash分片算法 都落在在了第一個節點
呢這套系統只能抗3w的并發
你的商品的key 都落在同一個節點上,導致我們所有的請求 都打在同一個節點上針對我們秒殺商品說白了,要緩存預熱的時候 你這個商品在那個節點上,你自己肯定要知道的我預熱的時候就得解決,我們通過一些redis命令,吧傾斜的商品進行移動,
或者我們可以用hashTag 把我們的商品進行分片
也就是說{ 1 ,2} 在一個節點上 { 3 ,4} 在一個節點上
其實說白了,我現在有10個秒殺商品.我其實來的10w并發 甚至更高的并發 都集中在1個商品上
我所有請求都只搶一個商品 呢意味著 你現在所有請求 又打到了某一個節點上
此時就不能支撐10w的并發了熱點商品問題 怎么提升它的并發
一個商品的并發請求就很高
怎么讓它扛到10w 的并發 有什么好的方案
我做秒殺的時候 我應該有一些預設 就不能把他的庫存放在一個redis節點上
我在做緩存預熱的時候 我就的要拆開了
就算此時都是搶茅臺,我自己做一個負載均衡的策略 第一個請求 搶第一個 第二個請求搶第二個節點的100個
我們可以利用conHashMap進行分段存儲,我們一個10w級別秒殺系統大概是這種的
我們在瞅瞅這個系統的架構中還有那些有問題 因為有問題 可能導致我們系統崩潰
我們此時除了滿足系統高并發之外 還要高可用
redis 減庫存 之后我們就丟到mq中 mq 用的時候 碰到過什么問題
mq丟消息怎么處理
mq消息擠壓怎么處理
mq消費的時候怎么保證冪等 這些問題肯定會導致我們系統不穩定 影響我們的可用性
我在發mq的時候 記錄一個日志表 然后等Mq消費成功之后 再去更新這個表狀態 從待處理改成已處理萬一我消息丟失了 我狀態就是待處理狀態,我后端可以搞個定時任務來輪詢待處理的任務 進行重發
消費的過程中怎么保證它的冪等
比如說你發mq失敗了,可能重試了,可能你一條消息發了2次,呢我下游可能同一個訂單有 入庫2次
就有可能生成2個訂單
對于mq 冪等怎么處理有的時候訂單id是在我服務端生成的 我訂單id是在我服務端生成的 我可以用messageId 做主鍵
我也可以用(userId+productId+acvitityId) 做個業務主鍵,(一般來說你是那個秒殺活動) 組合一個唯一的Id我下單的時候我查下(redis/db) 這個主鍵在不在 如果不存在的化 就代表它是一筆
mq消息擠壓 我后端消費來不及呢么快 消息擠壓了怎么處理
我mq 里面存在了上百萬條消息,這個時候會出現什么問題
我用戶在前端還等著了 現在異步下單 意味著它此時的圈圈會一直轉的
你這塊擠壓了有百萬 意味著 一個訂單生成個 很久才能被消費
用戶是等不了這么久的
我如果拿到這個消息 (是有發送時間的) 我判斷一下 如果這個消息是2分鐘以前發的 呢意味著這條消息
已經在mq中等了2分鐘了
我超過1分鐘 我直接吧消息丟掉、、
如果轉的超過2分鐘 還沒有查到 的化 我就認為你下單失敗了
因為這個訂單在1分鐘沒有被消費的時候 其實已經被丟掉了
假設此時搶購問題 redis集群出現問題怎么辦,mq集群出現問題了怎么辦