阿里云Redis讀寫分離典型場景:如何輕松搭建電商秒殺系統(tǒng)

轉(zhuǎn)自云棲社區(qū)

秒殺活動是絕大部分電商選擇的低價(jià)促銷饲握,推廣品牌的方式煌珊。不僅可以給平臺帶來用戶量笋鄙,還可以提高平臺知名度。一個好的秒殺系統(tǒng)怪瓶,可以提高平臺系統(tǒng)的穩(wěn)定性和公平性,獲得更好的用戶體驗(yàn)践美,提升平臺的口碑洗贰,從而提升秒殺活動的最大價(jià)值。

本次主要討論阿里云云數(shù)據(jù)庫Redis緩存設(shè)計(jì)高并發(fā)的秒殺系統(tǒng)陨倡。

秒殺的特征

秒殺活動對稀缺或者特價(jià)的商品進(jìn)行定時(shí)敛滋,定量售賣,吸引成大量的消費(fèi)者進(jìn)行搶購兴革,但又只有少部分消費(fèi)者可以下單成功绎晃。因此,秒殺活動將在較短時(shí)間內(nèi)產(chǎn)生比平時(shí)大數(shù)十倍杂曲,上百倍的頁面訪問流量和下單請求流量庶艾。

秒殺活動可以分為3個階段:

秒殺前:用戶不斷刷新商品詳情頁,頁面請求達(dá)到瞬時(shí)峰值擎勘。

秒殺開始:用戶點(diǎn)擊秒殺按鈕咱揍,下單請求達(dá)到瞬時(shí)峰值。

秒殺后:一部分成功下單的用戶不斷刷新訂單或者產(chǎn)生退單操作棚饵,大部分用戶繼續(xù)刷新商品詳情頁等待退單機(jī)會煤裙。

消費(fèi)者提交訂單,一般做法是利用數(shù)據(jù)庫的行級鎖噪漾。只有搶到鎖的請求可以進(jìn)行庫存查詢和下單操作硼砰。但是在高并發(fā)的情況下题翰,數(shù)據(jù)庫無法承擔(dān)如此大的請求遍愿,往往會使整個服務(wù)blocked,在消費(fèi)者看來就是服務(wù)器宕機(jī)桅咆。

秒殺系統(tǒng)

系統(tǒng)架構(gòu)圖

秒殺系統(tǒng)的流量雖然很高坞笙,但是實(shí)際有效流量是十分有限的。利用系統(tǒng)的層次結(jié)構(gòu)籍茧,在每個階段提前校驗(yàn)梯澜,攔截?zé)o效流量,可以減少大量無效的流量涌入數(shù)據(jù)庫吮龄。

利用瀏覽器緩存和CDN抗壓靜態(tài)頁面流量

秒殺前漓帚,用戶不斷刷新商品詳情頁午磁,造成大量的頁面請求。所以昧辽,我們需要把秒殺商品詳情頁與普通的商品詳情頁分開登颓。對于秒殺商品詳情頁盡量將能靜態(tài)化的元素盡量靜態(tài)化處理,除了秒殺按鈕需要服務(wù)端進(jìn)行動態(tài)判斷取具,其他的靜態(tài)數(shù)據(jù)可以緩存在瀏覽器和CDN上扁耐。這樣,秒殺前刷新頁面導(dǎo)致的流量進(jìn)入服務(wù)段的流量只有很小的一部分

利用阿里云讀寫分離Redis緩存攔截流量

CDN是第一級流量攔截块仆,第二級流量攔截我們使用支持讀寫分離的阿里云Redis。在這一階段我們主要讀取數(shù)據(jù)悔据,讀寫分離Redis能支持高大60萬以上qps的科汗,完全可以支持需求。

首先通過數(shù)據(jù)控制模塊怖亭,提前將秒殺商品的緩存到阿里云讀寫分離Redis坤检,并設(shè)置秒殺開始標(biāo)記:

"goodsId_count": 100 //總數(shù)"goodsId_start": 0 //開始標(biāo)記"goodsId_access": 0 //接受下單數(shù)

秒殺開始前,服務(wù)集群讀取goodsId_Start為0倾芝,直接返回未開始箭跳。

數(shù)據(jù)控制模塊將goodsId_start改為1,標(biāo)志秒殺開始。

服務(wù)集群緩存開始標(biāo)記位并開始接受請求脊岳,并記錄到redis中g(shù)oodsId_access,商品剩余數(shù)量為(goodsId_count - goodsId_access)奶躯。

當(dāng)接受下單數(shù)達(dá)到goodsId_count后亿驾,繼續(xù)攔截所有請求,商品剩余數(shù)量為0

可以看出儡蔓,最后成功參與下單的請求只有少部分可以被接受疼邀。在高并發(fā)的情況下,允許稍微多的流量進(jìn)入获询。因此可以控制接受下單數(shù)的比例。

利用阿里云主從版Redis緩存加速庫存扣量

成功參與下單梢薪,進(jìn)入下層服務(wù)尝哆,開始進(jìn)行訂單信息校驗(yàn),庫存扣量畜疾。為了避免直接訪問數(shù)據(jù)庫印衔,我們使用阿里云主從版Redis來進(jìn)行庫存扣量,阿里云主從版Redis提供10萬級別的QPS瞎暑。我們使用Redis來優(yōu)化庫存查詢与帆,提前攔截秒殺失敗的請求,將大大提高系統(tǒng)的整體吞吐量勿她。我們也是通過數(shù)據(jù)控制模塊提前將庫存存入Redis:

//我們將每個秒殺商品在redis中用一個hash結(jié)構(gòu)表示

"goodsId" : { "Total": 100 "Booked": 100}

扣量時(shí)阵翎,服務(wù)器通過請求Redis獲取下單資格,我們通過lua腳本實(shí)現(xiàn)砍聊,由于Redis時(shí)單線程模型贰军,lua可以保證多個命令的原子性:

lua腳本:

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腳本提前緩存在Redis词疼,然后調(diào)用EVALSHA調(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ù)通過判斷Redis是否返回?fù)屬弬€數(shù)n聘萨,即可知道此次請求是否扣量成功童太。

使用阿里云主從版Redis實(shí)現(xiàn)簡單的消息隊(duì)列異步下單入庫

扣量完成后胸完,需要進(jìn)行訂單入庫赊窥。如果商品數(shù)量較少的時(shí)候狸页,直接操作數(shù)據(jù)庫即可。如果秒殺的商品是1萬址遇,甚至10萬級別斋竞,那數(shù)據(jù)庫鎖沖突將帶來很大的性能瓶頸。因此浸剩,利用消息隊(duì)列組件鳄袍,當(dāng)秒殺服務(wù)將訂單信息寫入消息隊(duì)列后,即可認(rèn)為下單完成重罪,避免直接操作數(shù)據(jù)庫哀九。

消息隊(duì)列組件依然可以使用Redis實(shí)現(xiàn),在R2中用list數(shù)據(jù)結(jié)構(gòu)表示:

orderList { [0] = {訂單內(nèi)容} [1] = {訂單內(nèi)容} [2] = {訂單內(nèi)容} ...}

將訂單內(nèi)容寫入Redis:

LPUSH orderList {訂單內(nèi)容}

異步下單模塊從Redis中順序獲取訂單信息惨篱,并將訂單寫入數(shù)據(jù)庫:

BRPOP orderList 0

我們通過使用Redis作為消息隊(duì)列围俘,異步處理訂單入庫界牡,有效的提高了用戶的下單完成速度漾抬。

數(shù)據(jù)控制模塊,管理秒殺數(shù)據(jù)同步

最開始挽荠,我們利用阿里云讀寫分離Redis進(jìn)行流量限制,只讓部分流量進(jìn)入下單圈匆。對于下單檢驗(yàn)失敗和退單等情況,我們需要讓更多的流量進(jìn)來笆搓。因此纬傲,數(shù)據(jù)控制模塊需要定時(shí)將數(shù)據(jù)庫中的數(shù)據(jù)進(jìn)行一定的計(jì)算,同步到主從版Redis算墨,同時(shí)再同步到讀寫分離的Redis领猾,讓更多的流量進(jìn)來。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末面粮,一起剝皮案震驚了整個濱河市熬苍,隨后出現(xiàn)的幾起案子袁翁,更是在濱河造成了極大的恐慌,老刑警劉巖柄驻,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件焙压,死亡現(xiàn)場離奇詭異,居然都是意外死亡野哭,警方通過查閱死者的電腦和手機(jī)幻件,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進(jìn)店門绰沥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來贺待,“玉大人狠持,你說我怎么就攤上這事瞻润。” “怎么了正勒?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵傻铣,是天一觀的道長。 經(jīng)常有香客問我鸭限,道長两踏,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任赡麦,我火速辦了婚禮泛粹,結(jié)果婚禮上肮疗,老公的妹妹穿的比我還像新娘。我一直安慰自己们衙,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布砍艾。 她就那樣靜靜地躺著巍举,像睡著了一般懊悯。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上炭分,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天,我揣著相機(jī)與錄音捧毛,去河邊找鬼。 笑死呀忧,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的而账。 我是一名探鬼主播,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼泞辐,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了咐吼?” 一聲冷哼從身側(cè)響起吹缔,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤涛菠,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后俗冻,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡迄薄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年讥蔽,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片画机。...
    茶點(diǎn)故事閱讀 40,013評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡步氏,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出芋类,到底是詐尸還是另有隱情,我是刑警寧澤侯繁,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布贮竟,位于F島的核電站,受9級特大地震影響咕别,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜凫乖,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一帽芽、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧导街,春花似錦纤子、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至幔妨,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間古话,已是汗流浹背锁施。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工杖们, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留膊毁,地道東北人婚温。 一個月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓媳否,卻偏偏與公主長得像,于是被迫代替她去往敵國和親力图。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評論 2 355

推薦閱讀更多精彩內(nèi)容