自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

理論 | 秒殺系統(tǒng)設計注意點

系統(tǒng)
在秒殺的場景中,對于系統(tǒng)的要求其實就三個字:快、準、穩(wěn)。

 [[355121]]

在秒殺的場景中,對于系統(tǒng)的要求其實就三個字:快、準、穩(wěn)。

本文主要內容:

五個架構原則

數據要盡量少

首先是指用戶請求的數據能少就少。請求的數據包括上傳給系統(tǒng)的數據和系統(tǒng)返回給用戶的數據(通常就是網頁)。

請求數要盡量少

用戶請求的頁面返回后,瀏覽器渲染這個頁面還要包含其他的額外請求,比如說,這個頁面依賴的 CSS/JavaScript、圖片,以及 Ajax 請求等等都定義為“額外請求”,這些額外請求應該盡量少。

路徑要盡量短

就是用戶發(fā)出請求到返回數據這個過程中,需求經過的中間的節(jié)點數。

依賴要盡量少

指的是要完成一次用戶請求必須依賴的系統(tǒng)或者服務,這里的依賴指的是強依賴。

高可用

系統(tǒng)中的單點可以說是系統(tǒng)架構上的一個大忌,因為單點意味著沒有備份,風險不可控,我們設計分布式系統(tǒng)最重要的原則就是“消除單點”,另外一種叫法“高可用”。

架構是一種平衡的藝術,而最好的架構一旦脫離了它所適應的場景,一切都將是空談。我們需要記住的是,這里所說的幾點都只是一個個方向而已,我們應該盡量往這些方向上去努力,但也要考慮平衡其他因素。

如何做動靜分離

何為動靜數據

那到底什么才是動靜分離呢?所謂“動靜分離”,其實就是把用戶請求的數據(如 HTML 頁面)劃分為“動態(tài)數據”和“靜態(tài)數據”。簡單來說,“動態(tài)數據”和“靜態(tài)數據”的主要區(qū)別就是看頁面中輸出的數據是否和 URL、瀏覽者、時間、地域相關,以及是否含有 Cookie 等私密數據。

很多媒體類的網站,某一篇文章的內容不管是你訪問還是我訪問,它都是一樣的。所以它就是一個典型的靜態(tài)數據,但是它是個動態(tài)頁面。

我們如果現在訪問淘寶的首頁,每個人看到的頁面可能都是不一樣的,淘寶首頁中包含了很多根據訪問者特征推薦的信息,而這些個性化的數據就可以理解為動態(tài)數據了。

怎樣對靜態(tài)數據做緩存呢?

第一,你應該把靜態(tài)數據緩存到離用戶最近的地方。靜態(tài)數據就是那些相對不會變化的數據,因此我們可以把它們緩存起來。緩存到哪里呢?常見的就三種,用戶瀏覽器里、CDN 上或者在服務端的 Cache 中。你應該根據情況,把它們盡量緩存到離用戶最近的地方。

第二,靜態(tài)化改造就是要直接緩存 HTTP 連接。相較于普通的數據緩存而言,你肯定還聽過系統(tǒng)的靜態(tài)化改造。靜態(tài)化改造是直接緩存 HTTP 連接而不是僅僅緩存數據,如下圖所示,Web 代理服務器根據請求 URL,直接取出對應的 HTTP 響應頭和響應體然后直接返回,這個響應過程簡單得連 HTTP 協議都不用重新組裝,甚至連 HTTP 請求頭也不需要解析。

第三,讓誰來緩存靜態(tài)數據也很重要。不同語言寫的 Cache 軟件處理緩存數據的效率也各不相同。以 Java 為例,因為 Java 系統(tǒng)本身也有其弱點(比如不擅長處理大量連接請求,每個連接消耗的內存較多,Servlet 容器解析 HTTP 協議較慢),所以你可以不在 Java 層做緩存,而是直接在 Web 服務器層上做,這樣你就可以屏蔽 Java 語言層面的一些弱點;而相比起來,Web 服務器(如 Nginx、Apache、Varnish)也更擅長處理大并發(fā)的靜態(tài)文件請求。

如何做動靜分離的改造

  1. URL 唯一化
  2. 分離瀏覽者相關的因素
  3. 分離時間因素
  4. 異步化地域因素
  5. 去掉 Cookie

動靜分離的幾種架構方案

根據架構上的復雜度,有 3 種方案可選:

實體機單機部署:

統(tǒng)一 Cache 層:

加上CDN層:

CDN 化部署方案還有以下幾個特點:

  1. 把整個頁面緩存在用戶瀏覽器中;
  2. 如果強制刷新整個頁面,也會請求 CDN;
  3. 實際有效請求,只是用戶對“刷新搶寶”按鈕的點擊。

秒殺系統(tǒng)熱點數據如何處理?

什么是“熱點”

熱點分為熱點操作和熱點數據。

所謂“熱點操作”,例如大量的刷新頁面、大量的添加購物車、雙十一零點大量的下單等都屬于此類操作。對系統(tǒng)來說,這些操作可以抽象為“讀請求”和“寫請求”,這兩種熱點請求的處理方式大相徑庭,讀請求的優(yōu)化空間要大一些,而寫請求的瓶頸一般都在存儲層,優(yōu)化的思路就是根據 CAP 理論做平衡,這個內容我在“減庫存”一文再詳細介紹。

而“熱點數據”比較好理解,那就是用戶的熱點請求對應的數據。而熱點數據又分為“靜態(tài)熱點數據”和“動態(tài)熱點數據”。

所謂“靜態(tài)熱點數據”,就是能夠提前預測的熱點數據。例如,我們可以通過賣家報名的方式提前篩選出來,通過報名系統(tǒng)對這些熱點商品進行打標。另外,我們還可以通過大數據分析來提前發(fā)現熱點商品,比如我們分析歷史成交記錄、用戶的購物車記錄,來發(fā)現哪些商品可能更熱門、更好賣,這些都是可以提前分析出來的熱點。

所謂“動態(tài)熱點數據”,就是不能被提前預測到的,系統(tǒng)在運行過程中臨時產生的熱點。例如,賣家在抖音上做了廣告,然后商品一下就火了,導致它在短時間內被大量購買。

由于熱點操作是用戶的行為,我們不好改變,但能做一些限制和保護,所以本文我主要針對熱點數據來介紹如何進行優(yōu)化。

發(fā)現熱點數據

  1. 發(fā)現靜態(tài)熱點數據
  2. 發(fā)現動態(tài)熱點數據

處理熱點數據

優(yōu)化

優(yōu)化熱點數據最有效的辦法就是緩存熱點數據,如果熱點數據做了動靜分離,那么可以長期緩存靜態(tài)數據。但是,緩存熱點數據更多的是“臨時”緩存,即不管是靜態(tài)數據還是動態(tài)數據,都用一個隊列短暫地緩存數秒鐘,由于隊列長度有限,可以采用 LRU 淘汰算法替換。

限制

限制更多的是一種保護機制,限制的辦法也有很多,例如對被訪問商品的 ID 做一致性 Hash,然后根據 Hash 做分桶,每個分桶設置一個處理隊列,這樣可以把熱點商品限制在一個請求隊列里,防止因某些熱點商品占用太多的服務器資源,而使其他請求始終得不到服務器的處理資源。

隔離

秒殺系統(tǒng)設計的第一個原則就是將這種熱點數據隔離出來,不要讓 1% 的請求影響到另外的 99%,隔離出來后也更方便對這 1% 的請求做針對性的優(yōu)化 。其中隔離又可以分為:業(yè)務隔離、系統(tǒng)隔離、數據隔離。

流量削峰怎么做

就像城市里的道路,因為存在早高峰和晚高峰的問題,所以有了錯峰限行的解決方案。

削峰的存在,一是可以讓服務端處理變得更加平穩(wěn),二是可以節(jié)省服務器的資源成本。

針對秒殺這一場景,削峰從本質上來說就是更多地延緩用戶請求的發(fā)出,以便減少和過濾掉一些無效請求,它遵從“請求數要盡量少”的原則。

流量削峰思路

排隊

要對流量進行削峰,最容易想到的解決方案就是用消息隊列來緩沖瞬時流量,把同步的直接調用轉換成異步的間接推送,中間通過一個隊列在一端承接瞬時的流量洪峰,在另一端平滑地將消息推送出去。

除了消息隊列,類似的排隊方式還有很多,例如:

  • 利用線程池加鎖等待也是一種常用的排隊方式;
  • 先進先出、先進后出等常用的內存排隊算法的實現方式;
  • 把請求序列化到文件中,然后再順序地讀文件(例如基于 MySQL binlog 的同步機制)來恢復請求等方式。

可以看到,這些方式都有一個共同特征,就是把“一步的操作”變成“兩步的操作”,其中增加的一步操作用來起到緩沖的作用。

性能優(yōu)化

  • 減少編碼
  • 減少序列化
  • Java 極致優(yōu)化
  • 并發(fā)讀優(yōu)化

“減庫存”核心邏輯

這是非常重要的,其他所有步驟都是做一些輔助性的。庫存 100 件就賣 100 件,在數據庫里減到 0 就好了啊,這有什么麻煩的?是的,理論上是這樣,但是具體到業(yè)務場景中,“減庫存”就不是這么簡單了。

減庫存有哪幾種方式

在商品頁面點了“立即購買”按鈕,核對信息之后點擊“提交訂單”,這一步稱為下單操作。下單之后,你只有真正完成付款操作才能算真正購買,也就是俗話說的“落袋為安”。

減庫存操作一般有如下幾個方式:

下單減庫存

即當買家下單后,在商品的總庫存中減去買家購買數量。下單減庫存是最簡單的減庫存方式,也是控制最精確的一種,下單時直接通過數據庫的事務機制控制商品庫存,這樣一定不會出現超賣的情況。但是你要知道,有些人下完單可能并不會付款。

付款減庫存

即買家下單后,并不立即減庫存,而是等到有用戶付款后才真正減庫存,否則庫存一直保留給其他買家。但因為付款時才減庫存,如果并發(fā)比較高,有可能出現買家下單后付不了款的情況,因為可能商品已經被其他人買走了。

預扣庫存

這種方式相對復雜一些,買家下單后,庫存為其保留一定的時間(如 10 分鐘),超過這個時間,庫存將會自動釋放,釋放后其他買家就可以繼續(xù)購買。在買家付款前,系統(tǒng)會校驗該訂單的庫存是否還有保留:如果沒有保留,則再次嘗試預扣;如果庫存不足(也就是預扣失敗)則不允許繼續(xù)付款;如果預扣成功,則完成付款并實際地減去庫存。

高可用建設應該從哪里著手

說到系統(tǒng)的高可用建設,它其實是一個系統(tǒng)工程,需要考慮到系統(tǒng)建設的各個階段,也就是說它其實貫穿了系統(tǒng)建設的整個生命周期,如下圖所示:

架構階段

架構階段主要考慮系統(tǒng)的可擴展性和容錯性,要避免系統(tǒng)出現單點問題。例如多機房單元化部署,即使某個城市的某個機房出現整體故障,仍然不會影響整體網站的運轉。

編碼階段

編碼最重要的是保證代碼的健壯性,例如涉及遠程調用問題時,要設置合理的超時退出機制,防止被其他系統(tǒng)拖垮,也要對調用的返回結果集有預期,防止返回的結果超出程序處理范圍,最常見的做法就是對錯誤異常進行捕獲,對無法預料的錯誤要有默認處理結果。

測試階段

測試主要是保證測試用例的覆蓋度,保證最壞情況發(fā)生時,我們也有相應的處理流程。

發(fā)布階段

發(fā)布時也有一些地方需要注意,因為發(fā)布時最容易出現錯誤,因此要有緊急的回滾機制。

運行階段

運行時是系統(tǒng)的常態(tài),系統(tǒng)大部分時間都會處于運行態(tài),運行態(tài)最重要的是對系統(tǒng)的監(jiān)控要準確及時,發(fā)現問題能夠準確報警并且報警數據要準確詳細,以便于排查問題。

故障發(fā)生

故障發(fā)生時首先最重要的就是及時止損,例如由于程序問題導致商品價格錯誤,那就要及時下架商品或者關閉購買鏈接,防止造成重大資產損失。然后就是要能夠及時恢復服務,并定位原因解決問題。

在遇到大流量時,我們應該怎么最大化的保障我們的系統(tǒng)正常運行呢?

降級

所謂“降級”,就是當系統(tǒng)的容量達到一定程度時,限制或者關閉系統(tǒng)的某些非核心功能,從而把有限的資源保留給更核心的業(yè)務。它是一個有目的、有計劃的執(zhí)行過程,所以對降級我們一般需要有一套預案來配合執(zhí)行。如果我們把它系統(tǒng)化,就可以通過預案系統(tǒng)和開關系統(tǒng)來實現降級。

限流

限流就是當系統(tǒng)容量達到瓶頸時,我們需要通過限制一部分流量來保護系統(tǒng),并做到既可以人工執(zhí)行開關,也支持自動化保護的措施。

客戶端限流和服務端限流的優(yōu)缺點:

客戶端限流,好處可以限制請求的發(fā)出,通過減少發(fā)出無用請求從而減少對系統(tǒng)的消耗。缺點就是當客戶端比較分散時,沒法設置合理的限流閾值:如果閾值設的太小,會導致服務端沒有達到瓶頸時客戶端已經被限制;而如果設的太大,則起不到限制的作用。

服務端限流,好處是可以根據服務端的性能設置合理的閾值,而缺點就是被限制的請求都是無效的請求,處理這些無效的請求本身也會消耗服務器資源。

常見限流算法

計數器(固定窗口)算法

計數器算法是使用計數器在周期內累加訪問次數,當達到設定的限流值時,觸發(fā)限流策略。下一個周期開始時,進行清零,重新計數。

此算法在單機還是分布式環(huán)境下實現都非常簡單,使用redis的incr原子自增性和線程安全即可輕松實現。

滑動窗口算法

滑動窗口算法是將時間周期分為N個小周期,分別記錄每個小周期內訪問次數,并且根據時間滑動刪除過期的小周期。此算法可以很好的解決固定窗口算法的臨界問題。

漏桶算法

漏桶算法是訪問請求到達時直接放入漏桶,如當前容量已達到上限(限流值),則進行丟棄(觸發(fā)限流策略)。漏桶以固定的速率進行釋放訪問請求(即請求通過),直到漏桶為空。

令牌桶算法

令牌桶算法是程序以r(r=時間周期/限流值)的速度向令牌桶中增加令牌,直到令牌桶滿,請求到達時向令牌桶請求令牌,如獲取到令牌則通過請求,否則觸發(fā)限流策略

拒絕服務

如果限流還不能解決問題,最后一招就是直接拒絕服務了。當系統(tǒng)負載達到一定閾值時,例如 CPU 使用率達到 90% 或者系統(tǒng) load 值達到 2*CPU 核數時,系統(tǒng)直接拒絕所有請求,這種方式是最暴力但也最有效的系統(tǒng)保護方式。例如秒殺系統(tǒng),我們在如下幾個環(huán)節(jié)設計過載保護:

在最前端的 Nginx 上設置過載保護,當機器負載達到某個值時直接拒絕 HTTP 請求并返回 503 錯誤碼,在 Java 層同樣也可以設計過載保護。

拒絕服務可以說是一種不得已的兜底方案,用以防止最壞情況發(fā)生,防止因把服務器壓跨而長時間徹底無法提供服務。像這種系統(tǒng)過載保護雖然在過載時無法提供服務,但是系統(tǒng)仍然可以運作,當負載下降時又很容易恢復,所以每個系統(tǒng)和每個環(huán)節(jié)都應該設置這個兜底方案,對系統(tǒng)做最壞情況下的保護。

緩存問題

緩存雪崩

數據未加載到緩存中,或者緩存同時在大范圍中失效,導致所有請求查找數據庫,導致數據庫、CPU 和內存過載,甚至停機。

一個簡單的雪崩過程:

1) Redis 集群的大面積故障;

2) 緩存失敗,但仍有大量請求訪問緩存服務 Redis;

3) 在大量 Redis 請求失敗后,請求轉向數據庫;

4) 數據庫請求急劇增加,導致數據庫被打死;

5) 由于你應用程序服務大部分都依賴于數據庫和 Redis 服務,它很快就會導致服務器集群的雪崩,最后整個系統(tǒng)將徹底崩潰。

解決辦法:

事前:高可用的緩存

高可用的緩存是防止出現整個緩存故障。即使個別節(jié)點,機器甚甚至機房都關閉,系統(tǒng)仍然可以提供服務,Redis 哨兵(Sentinel) 和 Redis 集群(Cluster) 都可以做到高可用。

事中:緩存降級(臨時支持)

當訪問次數急劇增加導致服務出現問題時,我們如何確保服務仍然可用。在國內使用比較多的是 Hystrix,它通過熔斷、降級、限流三個手段來降低雪崩發(fā)生后的損失。只要確保數據庫不死,系統(tǒng)總可以響應請求,每年的春節(jié) 12306 我們不都是這么過來的嗎?只要還可以響應起碼還有搶到票的機會。

事后:Redis 備份和快速預熱

1) Redis 數據備份和恢復

2) 快速緩存預熱

緩存擊穿

緩存擊穿意味著當熱點數據存儲到期時,多個線程同時請求熱點數據。因為緩存剛過期,所有并發(fā)請求都會到數據庫查詢數據。

解決辦法:

實際上,在大多數實際業(yè)務場景中,緩存擊穿是實時發(fā)生的,但不會對數據庫造成太大壓力,因為一般的公司業(yè)務,并發(fā)量不會那么高。當然如果你不幸有這種情況,你可以通過設置這些熱點鍵,使其永遠不會過期。另一種方法是通過互斥鎖來控制查詢數據庫的線程訪問,但這種會導致系統(tǒng)的吞吐率下降,需要實際情況使用。

緩存穿透

緩存穿透是指查詢一個一定不存在的數據,因為緩存中也無該數據的信息,則會直接去數據庫層進行查詢,從系統(tǒng)層面來看像是穿透了緩存層直接達到db,從而稱為緩存穿透,沒有了緩存層的保護,這種查詢一定不存在的數據對系統(tǒng)來說可能是一種危險,如果有人惡意用這種一定不存在的數據來頻繁請求系統(tǒng),不,準確的說是攻擊系統(tǒng),請求都會到達數據庫層導致db癱瘓從而引起系統(tǒng)故障。

解決方案:

緩存穿透業(yè)內的解決方案已經比較成熟,主要常用的有以下幾種:

布隆過濾器:類似于哈希表的一種算法,用所有可能的查詢條件生成一個bitmap,在進行數據庫查詢之前會使用這個bitmap進行過濾,如果不在其中則直接過濾,從而減輕數據庫層面的壓力。

空值緩存:一種比較簡單的解決辦法,在第一次查詢完不存在的數據后,將該key與對應的空值(null或者對象里只有key)也放入緩存中,只不過設定為較短的失效時間,例如幾分鐘,這樣則可以應對短時間的大量的該key攻擊,設置為較短的失效時間是因為該值可能業(yè)務無關,存在意義不大,且該次的查詢也未必是攻擊者發(fā)起,無過久存儲的必要,故可以早點失效。

總結

由于本篇文章屬于理論篇,所以全篇沒有一行代碼,但是文中提出來的基本上就是秒殺系統(tǒng)所發(fā)生過的,每個系統(tǒng)可能發(fā)生的問題不同而已。

本文轉載自微信公眾號「Java后端技術全?!?,可以通過以下二維碼關注。轉載本文請聯系Java后端技術全棧公眾號。

 

責任編輯:武曉燕 來源: Java后端技術全棧
相關推薦

2024-10-10 17:23:31

2018-11-08 15:10:02

阿里雙十一架構

2025-02-20 00:01:00

2010-08-31 16:39:56

2023-12-12 09:06:06

2020-11-11 09:22:21

秒殺系統(tǒng)復盤

2019-12-19 10:10:45

秒殺系統(tǒng)高并發(fā)

2023-04-19 08:07:24

接口文檔設計

2019-11-18 08:21:04

秒殺系統(tǒng)高性能

2024-07-05 15:05:00

2019-07-23 13:32:13

Java開發(fā)代碼

2022-07-18 08:02:16

秒殺系統(tǒng)后端

2016-01-31 10:59:19

設計app

2020-10-14 07:20:53

高并發(fā)

2025-01-22 08:00:00

架構秒殺系統(tǒng)Java

2024-11-25 09:10:03

2019-11-12 15:11:45

秒殺流量高可用

2024-06-21 08:15:25

2019-06-27 09:50:49

高性能秒殺系統(tǒng)

2018-09-15 04:59:01

點贊
收藏

51CTO技術棧公眾號