解密Redis助力雙11背后電商秒殺系統(tǒng)(推薦)
背景
秒殺活動(dòng)是絕大部分電商選擇的低價(jià)促銷(xiāo),推廣品牌的方式。既可以給平臺(tái)帶來(lái)用戶(hù)量,還可以提高平臺(tái)知名度。一個(gè)好的秒殺系統(tǒng),可以提高平臺(tái)系統(tǒng)的穩(wěn)定性和公平性,獲得更好的用戶(hù)體驗(yàn),提升平臺(tái)的口碑,從而提升秒殺活動(dòng)的最大價(jià)值。
本文討論云數(shù)據(jù)庫(kù)Redis版緩存設(shè)計(jì)高并發(fā)的秒殺系統(tǒng)。
秒殺的特征
秒殺活動(dòng)對(duì)稀少或特價(jià)的商品進(jìn)行定時(shí)定量售賣(mài),吸引成大量的消費(fèi)者進(jìn)行搶購(gòu),但又只有少部分消費(fèi)者可以下單成功。因此,秒殺活動(dòng)將在一定時(shí)間內(nèi)產(chǎn)生比平時(shí)大幾十倍倍,上百倍的頁(yè)面訪(fǎng)問(wèn)流量和下單請(qǐng)求流量。
秒殺活動(dòng)可以分為3個(gè)階段:
- 秒殺前:用戶(hù)不斷刷新商品詳情頁(yè),頁(yè)面請(qǐng)求達(dá)到臨時(shí)開(kāi)頭。
- 秒殺開(kāi)始:用戶(hù)點(diǎn)擊秒殺按鈕,下單請(qǐng)求達(dá)到暫時(shí)提前。
- 秒殺后:一部分成功下單的用戶(hù)不斷刷新訂單或產(chǎn)生退單操作,大部分用戶(hù)繼續(xù)刷新商品詳情頁(yè)等待退單機(jī)會(huì)。
消費(fèi)者提交的訂單,一般做法是利用數(shù)據(jù)庫(kù)的行級(jí)鎖,只有搶到鎖的請(qǐng)求可以進(jìn)行庫(kù)存查詢(xún)和下單操作。但是在高并發(fā)的情況下,數(shù)據(jù)庫(kù)無(wú)法承受如此大的請(qǐng)求,往往需要整個(gè)服務(wù)被阻止,在消費(fèi)者看來(lái)就是服務(wù)器停機(jī)機(jī)。
秒殺系統(tǒng)
利用系統(tǒng)的層次結(jié)構(gòu),在每個(gè)階段提前重新驗(yàn)證,攔截?zé)o效流量,可以減少大量無(wú)效的流量涌入數(shù)據(jù)庫(kù)。
利用瀏覽器緩存和CDN抗壓靜態(tài)頁(yè)面流量
因此,我們需要把秒殺商品詳情頁(yè)與普通的商品詳情頁(yè)分開(kāi)。關(guān)于秒殺商品詳情頁(yè)試圖將能靜態(tài)化的元素靜態(tài)化處理,除了秒殺按鈕需要服務(wù)端進(jìn)行動(dòng)態(tài)判斷,其他的靜態(tài)數(shù)據(jù)可以緩存在瀏覽器和CDN上。這樣,秒殺前刷新頁(yè)面導(dǎo)致的流量進(jìn)入服務(wù)端的流量只有很小的一部分。
利用識(shí)讀分離Redis緩存攔截流量
CDN是第一級(jí)流量攔截,第二級(jí)流量攔截我們使用支持讀寫(xiě)分離的Redis。在這一階段我們主要讀取數(shù)據(jù),讀取分離Redis能支持高達(dá)60萬(wàn)以上qps,完全可以支持需求。
首先通過(guò)數(shù)據(jù)控制模塊,提前將秒殺商品緩存到標(biāo)識(shí)符分離Redis,并設(shè)置秒殺開(kāi)始標(biāo)記如下:
"goodsId_count": 100 //總數(shù) "goodsId_start": 0 //開(kāi)始標(biāo)記 "goodsId_access": 0 //接受下單數(shù)
- 秒殺開(kāi)始前,服務(wù)重新讀取goodsId_Start為0,直接返回未開(kāi)始。
- 數(shù)據(jù)控制模塊將goodsId_start改為1,標(biāo)志秒殺開(kāi)始。
- 服務(wù)最大化緩存開(kāi)始標(biāo)記位并開(kāi)始接受請(qǐng)求,并記錄到redis中g(shù)oodsId_access,商品剩余數(shù)量為(goodsId_count-goodsId_access)。
- 當(dāng)接受下單數(shù)達(dá)到goodsId_count后,繼續(xù)攔截所有請(qǐng)求,商品剩余數(shù)量為0。
可以?huà)伖猓詈蟪晒⑴c下單的請(qǐng)求只有少部分可以被接受。在高并發(fā)的情況下,允許稍微多的流量進(jìn)入。因此可以控制接受下單數(shù)的比例。
利用主從版Redis緩存加速庫(kù)存扣量
成功避免下單后,進(jìn)入下層服務(wù),開(kāi)始進(jìn)行訂單信息校驗(yàn),庫(kù)存扣量。為了避免直接訪(fǎng)問(wèn)數(shù)據(jù)庫(kù),我們使用主從版Redis來(lái)進(jìn)行庫(kù)存扣量,主從版Redis提供10萬(wàn)等級(jí)的QPS。使用Redis來(lái)優(yōu)化庫(kù)存查詢(xún),提前攔截秒殺失敗的請(qǐng)求,將大大提高系統(tǒng)的整體穩(wěn)定性。
通過(guò)數(shù)據(jù)控制模塊提前將庫(kù)存存入Redis,將每個(gè)秒殺商品在Redis中用一個(gè)hash結(jié)構(gòu)表示。
"goodsId" : { "Total": 100 "Booked": 100 }
扣量時(shí),服務(wù)器通過(guò)請(qǐng)求Redis獲取下單資格,通過(guò)以下lua腳本實(shí)現(xiàn),通過(guò)Redis是單線(xiàn)程模型,lua可以保證多個(gè)命令的原子性。
local n = tonumber(ARGV[1]) if not n or n == 0 then return 0 end local vals = redis.call("HMGET", KEYS[1], "Total", "Booked"); local total = tonumber(vals[1]) local blocked = tonumber(vals[2]) if not total or not blocked then return 0 end if blocked + n <= total then redis.call("HINCRBY", KEYS[1], "Booked", n) return n; end return 0
先使用SCRIPT LOAD
將lua腳本EVALSHA
預(yù)先緩存在Redis,然后調(diào)用調(diào)用腳本,比直接調(diào)用EVAL
節(jié)省網(wǎng)絡(luò)帶寬:
redis 127.0.0.1:6379>SCRIPT LOAD "lua code" "438dd755f3fe0d32771753eb57f075b18fed7716" redis 127.0.0.1:6379>EVAL 438dd755f3fe0d32771753eb57f075b18fed7716 1 goodsId 1
秒殺服務(wù)通過(guò)判斷Redis是否返回?fù)屬?gòu)個(gè)數(shù)n,即可知道此次請(qǐng)求是否扣量成功。
使用主從版Redis實(shí)現(xiàn)簡(jiǎn)單的消息異步下單入庫(kù)
如果商品數(shù)量減少的時(shí)候,直接操作數(shù)據(jù)庫(kù)即可。如果秒殺的商品是1萬(wàn),甚至10萬(wàn)等級(jí),那數(shù)據(jù)庫(kù)鎖沖突將帶來(lái)很大的性能優(yōu)勢(shì)。。因此,利用消息組件,當(dāng)秒殺服務(wù)將訂單信息寫(xiě)入消息變量后,即可認(rèn)為下單完成,避免直接操作數(shù)據(jù)庫(kù)。
消息模塊組件依然可以使用Redis實(shí)現(xiàn),在R2中用列表數(shù)據(jù)結(jié)構(gòu)表示。
```java orderList { [0] = {訂單內(nèi)容} [1] = {訂單內(nèi)容} [2] = {訂單內(nèi)容} ... }
將訂單內(nèi)容寫(xiě)入
```java LPUSH orderList {訂單內(nèi)容}
初步下單模塊從Redis中順序獲取訂單信息,將訂單寫(xiě)入數(shù)據(jù)庫(kù)。
```java BRPOP orderList 0
通過(guò)使用Redis作為消息收發(fā)器,異步處理訂單入庫(kù),有效的提高了用戶(hù)的下單完成速度。
數(shù)據(jù)控制模塊管理秒殺數(shù)據(jù)同步
最開(kāi)始,利用識(shí)別分離Redis進(jìn)行流量限制,只讓部分流量進(jìn)入下單。對(duì)于下單檢驗(yàn)失敗和退單等情況,需要讓更多的流量進(jìn)來(lái)。因此,數(shù)據(jù)控制模塊需要定時(shí)將數(shù)據(jù)庫(kù)中的數(shù)據(jù)進(jìn)行一定的計(jì)算,同步到主從版Redis,同時(shí)再同步到讀寫(xiě)分離的Redis,讓更多的流量進(jìn)來(lái)。
總結(jié)
到此這篇關(guān)于解密Redis助力雙11背后電商秒殺系統(tǒng)的文章就介紹到這了,更多相關(guān)redis電商秒殺系統(tǒng)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
redis慢查詢(xún)?nèi)罩镜脑L(fǎng)問(wèn)和管理方式
這篇文章主要介紹了redis慢查詢(xún)?nèi)罩镜脑L(fǎng)問(wèn)和管理方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12redis集合類(lèi)型_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章給大家介紹了redis集合類(lèi)型的常用方法,感興趣的朋友參考下吧2017-08-08Redis+Lua腳本實(shí)現(xiàn)計(jì)數(shù)器接口防刷功能(升級(jí)版)
這篇文章主要介紹了Redis+Lua腳本實(shí)現(xiàn)計(jì)數(shù)器接口防刷功能,使用腳本使得set命令和expire命令一同達(dá)到Redis被執(zhí)行且不會(huì)被干擾,在很大程度上保證了原子操作,對(duì)Redis實(shí)現(xiàn)計(jì)數(shù)器接口防刷功能感興趣的朋友一起看看吧2022-02-02Redis開(kāi)啟鍵空間通知實(shí)現(xiàn)超時(shí)通知的步驟詳解
這篇文章主要介紹了Redis開(kāi)啟鍵空間通知實(shí)現(xiàn)超時(shí)通知的步驟,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06Redis如何統(tǒng)計(jì)用戶(hù)訪(fǎng)問(wèn)量
這篇文章主要介紹了Redis如何統(tǒng)計(jì)用戶(hù)訪(fǎng)問(wèn)量問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07從零搭建SpringBoot2.X整合Redis框架的詳細(xì)教程
這篇文章主要介紹了從零搭建SpringBoot2.X整合Redis框架的詳細(xì)教程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-12-12