秒殺系統的技術難點與解決方案

zmy愛吃炸雞發表於2020-09-17

系統面臨的瓶頸是什麼

我們先了解一下,秒殺系統中具體有什麼問題需要解決呢?給大家畫一張圖:

 

 

假如我們的系統有了秒殺的業務,那麼會有海量的使用者訪問我們的訂單系統叢集,其實這裡還不是技術的瓶頸,只要擴充套件訂單系統叢集,增加訂單系統的機器數量就可以抗下這樣甚至更高的高併發情況。

 

那麼技術瓶頸是什麼呢?

我們再來看資料庫部分,你會發現無論你的訂單系統叢集增加多少機器,它們訪問的還是一個資料庫。那麼每次面對秒殺系統這樣的活動時,資料庫要承受的壓力是極大的,很可能因此當機,導致整個系統崩掉,後果是很可怕的。

由此我們分析出,資料庫是秒殺系統面臨的一大瓶頸。

 

如何解決秒殺系統的瓶頸

剛才我們談到,秒殺系統面臨的技術瓶頸是資料庫,那麼我們如何解決呢?是不是要部署更多的資料庫伺服器,對資料庫進行分庫分表,然後讓更多的資料庫伺服器共同抗下高併發的情況呢?

這種分庫分表的策略是這樣的,假設我們目前操作的是一個庫中的一張訂單表,那麼分庫後就變成了多個庫,每個庫裡都只存一部分的訂單資料,分庫策略可以是按時間戳或者雜湊演算法計算得出(這不是本篇重點,以後會有單獨的資料庫專題討論),分表呢就是可以在一個庫裡對訂單表再次拆分成多張表,資料再次分片儲存。

這種模式有什麼好處呢?

好處其實是顯而易見的,我們的高併發請求可以平均分配到多臺資料庫上,整個的資料庫叢集可以共同承擔高併發帶來的壓力,而且也可以透過擴充套件資料庫叢集實現可以承擔更高併發的能力。

說到這裡,小夥伴們是不是覺得,這個問題就這麼解決了呢?

可以明確的告訴大家,這種解決方法是很 不靠譜的,除非公司的技術能力太弱,沒有人能搭建出更可靠的架構才會選擇這種下下策,透過堆疊機器數量來抵抗高併發下的壓力。

試著想一下,假如我們的系統很受客戶歡迎,使用者量日漸增長,達到了海量的使用者數,難道我們要不停的增加伺服器數量嗎?

伺服器的成本是不是有點偏高了呢?

所以要解決這個問題,我們的出發點一定要正確,就是 不能透過不停的增加機器解決這種問題,而是在有限的資源下設計出更優雅的架構來解決,這樣的方法才是上策。

 

前臺頁面的最佳化

知道了我們應該在有限資源下進行架構最佳化,那麼我們先思考一個問題。

使用者參加秒殺活動的時候,是如何作業系統的呢?

就拿雙十一搶購來說,在00:00的時候就是秒殺的時候,那麼很多使用者會提前幾分鐘把手機開啟到對應的頁面,沒到時間就開始不停的重新整理頁面,等待秒殺開始那一刻的到來。

那麼小夥伴們有沒有考慮過, 這些要重新整理的頁面都是從哪裡來的呢?

我們的頁面其實也是要有自己專門的訂單頁面伺服器的,主要用於提供前端的訪問頁面,基本結構如下圖:

 

所以, 首先接受高併發請求的系統是前端頁面系統。

大家思考一個問題,如果平時不是秒殺的時候,使用者看的商品可能都是不同的,但是一旦有秒殺活動,可能有大量的使用者一起不停的重新整理同一個商品的同一個頁面,對系統造成壓力。

那麼對於這個問題,我們應該怎麼解決呢?

今天介紹的解決方案就是 頁面資料的靜態化+多級快取的策略。

 

頁面資料靜態化

我們先來聊一聊什麼是頁面資料的動態化。

假設我們的前端頁面是動態化的,那麼使用者每次訪問頁面,都會向頁面系統傳送請求獲取資料,然後前端頁面根據獲取的資料渲染頁面,一般來說系統的演進都是從這種動態化開始的,比如jsp頁面。

那麼如何實現頁面的靜態化呢,其實就是改變頁面獲取資料的方式,每次獲取資料不再是透過頁面系統查詢資料庫而是從別的地方獲取資料,避免每次都去訪問後端資料庫,對系統造成壓力。

 

多級快取

瞭解的靜態化的思想,那麼我們再來看看多級快取是什麼,我們要聊的多級快取指的是 CDN+Nginx+Redis的多級快取架構。

什麼意思呢?就是說頁面的資料首先放一份到離使用者最近的CDN上邊。

可能有的小夥伴不理解CDN,給大家簡單掃一下盲。

比如我們的系統伺服器部署在北京,訪問我們系統的使用者在海南,那麼它每次訪問我們系統是要到我們北京的伺服器上面獲取資料嗎?

不是的,我們是可以把靜態化的頁面資料部署到海南的CDN上邊去的,而海南的使用者就可以透過CDN獲取到我們系統的頁面資料。

這個CDN都是各種雲廠商提供的服務,它就是我們架構中的 第一級快取

如果由於CDN中快取過期等原因,導致沒有從CDN中得到頁面資料,那麼此時使用者就會將這個請求傳送到我們北京的伺服器上邊,但是這個時候系統不是直接查詢資料庫返回資料的,而是先訪問Nginx伺服器上的快取。

Nginx是可以基於Lua指令碼實現本地快取的,我們可以提前吧頁面資料放到Nginx快取中,作為 第二級的快取

如果Nginx上邊也沒有想要的資料呢?

那麼此時可以透過Nginx上的lua指令碼傳送請求到Redis叢集中載入資料,Redis叢集就作為我們多級快取架構的 第三級快取

如果在Redis叢集中還是沒有找到資料,我們再去從資料庫載入出來,並更新到快取裡。

透過這樣一套多級快取的架構,我們就可以實現頁面的靜態化資料的儲存(資料可能就是一段json串),這樣對於我們的頁面伺服器本身壓力就非常的小了。

架構圖如下:


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69983768/viewspace-2721957/,如需轉載,請註明出處,否則將追究法律責任。

相關文章