阿里雲Redis讀寫分離典型場景:如何輕鬆搭建電商秒殺系統

背景redis

秒殺活動是絕大部分電商選擇的低價促銷,推廣品牌的方式。不只能夠給平臺帶來用戶量,還能夠提升平臺知名度。一個好的秒殺系統,能夠提升平臺系統的穩定性和公平性,得到更好的用戶體驗,提高平臺的口碑,從而提高秒殺活動的最大價值。數據庫

本次主要討論阿里云云數據庫Redis緩存設計高併發的秒殺系統。瀏覽器

秒殺的特徵緩存

秒殺活動對稀缺或者特價的商品進行定時,定量售賣,吸引成大量的消費者進行搶購,但又只有少部分消費者能夠下單成功。所以,秒殺活動將在較短期內產生比平時大數十倍,上百倍的頁面訪問流量和下單請求流量。服務器

秒殺活動能夠分爲3個階段:網絡

秒殺前:用戶不斷刷新商品詳情頁,頁面請求達到瞬時峯值。數據結構

秒殺開始:用戶點擊秒殺按鈕,下單請求達到瞬時峯值。架構

秒殺後:一部分紅功下單的用戶不斷刷新訂單或者產生退單操做,大部分用戶繼續刷新商品詳情頁等待退單機會。併發

消費者提交訂單,通常作法是利用數據庫的行級鎖。只有搶到鎖的請求能夠進行庫存查詢和下單操做。可是在高併發的狀況下,數據庫沒法承擔如此大的請求,每每會使整個服務blocked,在消費者看來就是服務器宕機。異步

秒殺系統

系統架構圖

 

秒殺系統的流量雖然很高,可是實際有效流量是十分有限的。利用系統的層次結構,在每一個階段提早校驗,攔截無效流量,能夠減小大量無效的流量涌入數據庫。

利用瀏覽器緩存和CDN抗壓靜態頁面流量

秒殺前,用戶不斷刷新商品詳情頁,形成大量的頁面請求。因此,咱們須要把秒殺商品詳情頁與普通的商品詳情頁分開。對於秒殺商品詳情頁儘可能將能靜態化的元素儘可能靜態化處理,除了秒殺按鈕須要服務端進行動態判斷,其餘的靜態數據能夠緩存在瀏覽器和CDN上。這樣,秒殺前刷新頁面致使的流量進入服務段的流量只有很小的一部分

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

CDN是第一級流量攔截,第二級流量攔截咱們使用支持讀寫分離的阿里雲Redis。在這一階段咱們主要讀取數據,讀寫分離Redis能支持高大60萬以上qps的,徹底能夠支持需求。

首先經過數據控制模塊,提早將秒殺商品的緩存到阿里雲讀寫分離Redis,並設置秒殺開始標記:

 

秒殺開始前,服務集羣讀取goodsId_Start爲0,直接返回未開始。

數據控制模塊將goodsId_start改成1,標誌秒殺開始。

服務集羣緩存開始標記位並開始接受請求,並記錄到redis中goodsId_access,商品剩餘數量爲(goodsId_count - goodsId_access)。

當接受下單數達到goodsId_count後,繼續攔截全部請求,商品剩餘數量爲0

能夠看出,最後成功參與下單的請求只有少部分能夠被接受。在高併發的狀況下,容許稍微多的流量進入。所以能夠控制接受下單數的比例。

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

成功參與下單,進入下層服務,開始進行訂單信息校驗,庫存扣量。爲了不直接訪問數據庫,咱們使用阿里雲主從版Redis來進行庫存扣量,阿里雲主從版Redis提供10萬級別的QPS。咱們使用Redis來優化庫存查詢,提早攔截秒殺失敗的請求,將大大提升系統的總體吞吐量。咱們也是經過數據控制模塊提早將庫存存入Redis;

//咱們將每一個秒殺商品在redis中用一個hash結構表示

 

扣量時,服務器經過請求Redis獲取下單資格,咱們經過lua腳本實現,因爲Redis時單線程模型,lua能夠保證多個命令的原子性;

lua腳本:

 

先使用SCRIPT LOAD將lua腳本提早緩存在Redis,而後調用EVALSHA調用腳本,比直接調用EVAL節省網絡帶寬:

 

秒殺服務經過判斷Redis是否返回搶購個數n,便可知道這次請求是否扣量成功。

使用阿里雲主從版Redis實現簡單的消息隊列異步下單入庫

扣量完成後,須要進行訂單入庫。若是商品數量較少的時候,直接操做數據庫便可。若是秒殺的商品是1萬,甚至10萬級別,那數據庫鎖衝突將帶來很大的性能瓶頸。所以,利用消息隊列組件,當秒殺服務將訂單信息寫入消息隊列後,便可認爲下單完成,避免直接操做數據庫。

消息隊列組件依然可使用Redis實現,在R2中用list數據結構表示:

 

將訂單內容寫入Redis:

 

異步下單模塊從Redis中順序獲取訂單信息,並將訂單寫入數據庫:

 

咱們經過使用Redis做爲消息隊列,異步處理訂單入庫,有效的提升了用戶的下單完成速度。

數據控制模塊,管理秒殺數據同步

最開始,咱們利用阿里雲讀寫分離Redis進行流量限制,只讓部分流量進入下單。對於下單檢驗失敗和退單等狀況,咱們須要讓更多的流量進來。所以,數據控制模塊須要定時將數據庫中的數據進行必定的計算,同步到主從版Redis,同時再同步到讀寫分離的Redis,讓更多的流量進來。

Java架構大牛羣:697579751

相關文章
相關標籤/搜索