淺談Redis在秒殺場景的作用
秒殺業(yè)務特點:限時限量,業(yè)務系統(tǒng)要處理瞬時高并發(fā)請求,Redis是必需品。
秒殺可分成秒殺前、秒殺中和秒殺后三階段,每個階段的請求處理需求不同,Redis具體在秒殺場景的哪個環(huán)節(jié)起到作用呢?
1 秒殺負載特征
秒殺商品的庫存量<<購買該商品的用戶數(shù),且會限定用戶只能在一定時間段內購買。
這給秒殺系統(tǒng)帶來兩個明顯負載特征:
1.1 瞬時并發(fā)訪問量很高
一般DB每秒只能支撐k級并發(fā),而Redis并發(fā)能達到w級。所以,當大量并發(fā)請求涌入秒殺系統(tǒng)時,要使用Redis先攔截大部分請求,避免大量請求直接發(fā)給DB
1.2 讀多寫少
讀還是簡單的查詢操作。秒殺下,用戶需先查驗商品是否還有庫存(即根據(jù)商品ID查詢該庫存量),只有庫存有余量時,秒殺系統(tǒng)才能進行庫存扣減、下單??杀镜鼐彺姹4鎺齑媸欠駷?0 的標識,避免再請求 redis。
庫存查驗操作是典型KV查詢,Redis正滿足。但秒殺只有小部分用戶能成功下單,所以:
商品庫存查詢操作(讀操作)>>庫存扣減、下單操作(寫操作)
一般把秒殺活動分成三個階段:
2 秒殺階段
2.1 秒殺前
用戶不斷刷新商品詳情頁,導致詳情頁瞬時請求量猛增。
一般盡量靜態(tài)化商品詳情頁的頁面元素,然后使用CDN或瀏覽器緩存這些靜態(tài)化元素。
秒殺前的大量請求可直接由CDN或瀏覽器緩存服務,不會到達服務端。
2.2 秒殺中
大量用戶點擊商品詳情頁上的秒殺按鈕,會產生大量的并發(fā)請求查詢庫存。一旦某個請求查詢到有庫存,緊接著系統(tǒng)就會進行庫存扣減。然后,系統(tǒng)會生成實際訂單,并進行后續(xù)處理,例如訂單支付和物流服務。如果請求查不到庫存,就會返回。用戶通常會繼續(xù)點擊秒殺按鈕,繼續(xù)查詢庫存。
該階段主要操作:
- 庫存查驗
- 庫存扣減
- 訂單處理
每個秒殺請求都會查詢庫存,而請求只有查到有庫存余量,后續(xù)的庫存扣減和訂單處理才會被執(zhí)行。所以,該階段最大并發(fā)壓力在庫存查驗。就需使用Redis保存庫存量,請求直接從Redis讀庫存并查驗。
庫存扣減和訂單處理是否都可交給后端DB執(zhí)行?
訂單處理可在DB執(zhí)行,但庫存扣減操作,不能交給DB。
為何非在DB處理訂單呢?
訂單處理涉及支付、商品出庫、物流等多個關聯(lián)操作,這些操作本身涉及DB中的多張表,要保證事務性,需在DB完成。
訂單處理時,請求壓力已不大,DB完全可支撐。
為啥庫存扣減操作不能在DB執(zhí)行
一旦請求查到有庫存,即發(fā)送該請求的用戶獲得商品購買資格,用戶就會下單了。同時,商品庫存余量也需-1。
若把庫存扣減的操作放到DB,會帶來風險:
額外開銷
Redis保存庫存量,而庫存量最新值又是DB在維護,所以DB更新后,還要和Redis進行同步,這增加額外操作邏輯
下單量>實際庫存量,超賣!
由于DB處理性能較慢,無法及時更新庫存余量,可能導致大量庫存查驗請求讀到舊庫存值,并下單。就會出現(xiàn)下單數(shù)量>實際庫存量,導致超賣
所以,要在Redis進行庫存扣減:
- 當庫存查驗完成后,一旦庫存有余量,立即在Redis扣庫存
- 為避免請求查詢到舊庫存值,庫存查驗、庫存扣減兩個操作需保證原子性
秒殺中需要Redis參與的兩個環(huán)節(jié):
2.3 秒殺結束后
該階段,可能還有部分用戶刷新商品詳情頁,嘗試等待有其他用戶退單。而已成功下單的用戶會刷新訂單詳情,跟蹤訂單進度。
不過,此階段的用戶請求量已下降很多,服務器端一般都能支撐。
3 Redis可支撐秒殺的特性
3.1 支持高并發(fā)
Redis先天支持。且若有多個秒殺商品,也可使用切片集群,用不同實例保存不同商品的庫存,避免使用單實例導致所有秒殺請求都集中在一個實例。
使用切片集群時,先CRC計算不同秒殺商品K對應Slot,然后在分配Slot和實例對應關系時,才能把不同秒殺商品對應的Slot分配到不同實例保存。
3.2 保證庫存查驗和庫存扣減的原子性
使用Redis的原子操作或分布式鎖。
4 基于原子操作支撐秒殺
秒殺中的一個商品的庫存對應兩個信息:
- 總庫存量
- 已秒殺量
這種數(shù)據(jù)模型正好一個key(商品ID)對應兩個屬性(總庫存量和已秒殺量),可用Hash保存:
key: itemID value: {total: N, ordered: M}
itemID 商品編號total,總庫存量ordered,已秒殺量
因為庫存查驗、庫存扣減這兩個操作要保證一起執(zhí)行,一個直接的方法就是使用Redis的原子操作。
庫存查驗、庫存扣減是兩個操作,需Lua腳本保證原子執(zhí)行:
#獲取商品庫存信息 local counts = redis.call("HMGET", KEYS[1], "total", "ordered"); #將總庫存轉換為數(shù)值 local total = tonumber(counts[1]) #將已被秒殺的庫存轉換為數(shù)值 local ordered = tonumber(counts[2]) #如果當前請求的庫存量加上已被秒殺的庫存量仍然小于總庫存量,就可以更新庫存 if ordered + k <= total then #更新已秒殺的庫存量 redis.call("HINCRBY",KEYS[1],"ordered",k) return k; end return 0
然后就能在Redis客戶端,使用EVAL命令執(zhí)行腳本??蛻舳烁鶕?jù)腳本返回值,確定秒殺是否成功:
- 返回值k,成功
- 0,失敗
5 基于分布式鎖支撐秒殺
讓客戶端向Redis申請分布式鎖,拿到鎖的客戶端才能執(zhí)行庫存查驗、庫存扣減。
這樣大量秒殺請求就會在爭奪分布式鎖時被過濾掉。
庫存查驗、扣減也不用原子操作了,因為多個并發(fā)客戶端只有一個客戶端能夠拿到鎖,已保證客戶端并發(fā)訪問的互斥性。
// 使用商品ID作為key key = itemID // 使用客戶端唯一標識作為value val = clientUniqueID //申請分布式鎖,Timeout是超時時間 lock =acquireLock(key, val, Timeout) //當拿到鎖后,才能進行庫存查驗和扣減 if(lock == True) { //庫存查驗和扣減 availStock = DECR(key, k) //庫存已經扣減完了,釋放鎖,返回秒殺失敗 if (availStock < 0) { releaseLock(key, val) return error } //庫存扣減成功,釋放鎖 else{ releaseLock(key, val) //訂單處理 } } //沒有拿到鎖,直接返回 else return
使用分布式鎖時,客戶端要先向Redis請求鎖,只有請求到鎖,才能進行庫存查驗等操作,這樣客戶端在爭搶分布式鎖時,大部分秒殺請求本身就會因為搶不到鎖而被攔截。
推薦使用切片集群中的不同實例來分別保存分布式鎖和商品庫存信息。秒殺請求會先訪問保存分布式鎖的實例。若客戶端沒拿到鎖,這些客戶端就不會查詢商品庫存,減輕保存庫存信息的實例的壓力。
6 總結
秒殺系統(tǒng)是個系統(tǒng)性工程,Redis實現(xiàn)對庫存查驗、扣減環(huán)節(jié)的支撐。
此外,還有環(huán)節(jié)需要處理:
前端靜態(tài)頁面的設計
秒殺頁面上能靜態(tài)化處理的頁面元素,要盡量靜態(tài)化,充分利用CDN或瀏覽器緩存服務秒殺開始前的請求
請求攔截和流控
在秒殺系統(tǒng)的接入層,對惡意請求進行攔截,避免對系統(tǒng)的惡意攻擊,例如使用黑名單禁止惡意IP進行訪問。如果Redis實例的訪問壓力過大,為了避免實例崩潰,我們也需要在接入層進行限流,控制進入秒殺系統(tǒng)的請求數(shù)量。
庫存信息過期時間處理
Redis中保存的庫存信息其實是數(shù)據(jù)庫的緩存,為了避免緩存擊穿問題,不要給庫存信息設置過期時間。
數(shù)據(jù)庫訂單異常處理。如果數(shù)據(jù)庫沒能成功處理訂單,可以增加訂單重試功能,保證訂單最終能被成功處理。
資源隔離
秒殺活動帶來的請求流量巨大,我們需要把秒殺商品的庫存信息用單獨的實例保存,而不要和日常業(yè)務系統(tǒng)的數(shù)據(jù)保存在同一個實例上,這樣可以避免干擾業(yè)務系統(tǒng)的正常運行。
到此這篇關于淺談Redis在秒殺場景的作用的文章就介紹到這了,更多相關Redis 秒殺內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Redis高并發(fā)防止秒殺超賣實戰(zhàn)源碼解決方案
本文主要介紹了Redis高并發(fā)防止秒殺超賣實戰(zhàn)源碼解決方案,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-10-10Redis Cluster集群動態(tài)擴容的實現(xiàn)
本文主要介紹了Redis Cluster集群動態(tài)擴容的實現(xiàn),文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學習學習吧2021-07-07使用lua+redis解決發(fā)多張券的并發(fā)問題
這篇文章主要介紹了使用lua+redis解決發(fā)多張券的并發(fā)問題,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-01-01