畢業這一年多來,對於學生時代面試「必考」的高併發高可用,主要是高併發狀態下的讀介面,保證其處於高可用狀態,有了一些實戰的經驗,這裡記錄和總結一下。
在我看來,如果乙個後端流程要能夠扛住高併發大流量,必須嚴格經歷以下幾個流程:
首先我們需要梳理乙個業務流程的關鍵路徑以及次要路徑,比如展示一段商品列表,最核心的過程就是要使得商品列表給使用者正常展示,不影響使用者進入商詳和下單,即商品的列表,以及商品的基本屬性是主業務流程。
而關於商品的其他屬性,比如商品的標籤、商品包含什麼優惠券、商品有哪些服務能力等等,這些其實屬於對商品列表產出錦上添花的功能,是次要流程。
對於次要流程,除了得保證將其摘除時不影響主要流程外,還需要嚴格配置好每一段次要流程的超時時間,如果呼叫超時,需要及時斷掉以免影響到主流程。
限流的目的是通過對併發訪問/請求進行限速或者乙個時間視窗內的請求進行限速來保護系統,一旦達到限制速率則可以拒絕服務、排隊或等待、直接降級。
比如商品列表,排序的邏輯通常有乙個推薦服務來展示,而這個推薦服務通常不是只服務於單一業務。如果因為我們業務使得推薦服務負載過高,可能會影響到其他業務的正常展示,所以需要對下游推薦業務做好限流。
而限流之後,如何展示本來應該出現的資訊,則取決於這些資訊是否屬於關鍵路徑。對於非關鍵路徑,直接使其不展示即可;對於關鍵路徑,則需要做好必要的兜底,具體如何兜底,會在之後介紹。
降級的最終目的是為了保證核心服務可用,即我們之前梳理的關鍵路徑是可用的,其可以分為主動降級和被動降級。
比如下游某個服務突然不可用時,我們自己的服務可以通過灰度開關等方式,主動切換到不依賴該下游服務的狀態,只要做好了對應的兜底,或者說是屬於非關鍵路徑,我們的業務並不會受到下游服務掛掉的影響。
被動降級是指我們自己服務,檢測到下游服務的成功率**嚴重時,可以切換為不依賴該下游服務的狀態,保證自身主業務的正常執行。
兜底是每個高併發業務最最重要的環節,對於關鍵路徑上的資訊,在保證資料時效性的前提下,必須做好各種快取兜底,使得在下游服務全部異常時,本地依然有對應的資料結果展示出來。
兜底快取可以分為兩種,一種是啟動定時任務主動重新整理。比如商品列表,我們可以使用乙個定時任務,定時從資料表中,針對每個類目,拉取前n條商品id,快取在redis快取中。而redis快取在高併發下也並不是絕對可靠的(實際上經常抖動),我們可以使得每個例項啟動乙個定時任務,定時從redis中拉取必要資訊,在本地做local cache,這種情況下,介面的瓶頸基本是在機器的cpu和閘道器了,之後只需要堆機器即可橫向擴充套件流量的承載量。(至於為啥先拉到redis,我們的例項經常是幾百個,如果全部併發訪問資料庫,可能直接將資料庫打爆)
過載保護元件,是對服務的每個介面做乙個自動的評級,當服務的負載到了一定程度時,會優先保障重要的介面,以及重要的使用者訪問請求得到返回。
壓測是每個高併發業務的必經過程,通過壓測,可以讓我們模擬實際高併發狀態下服務的抗壓情況,經常的業務可以讓我們對業務的各個流程,限流、降級等情況更加了解,最好每次業務迭代完成後都進行對應的壓測。
用到的流控元件主要是阿里巴巴的sentiel,雖然似乎只支援單機限流,但是已經可以滿足絕大多數的高併發場景了。
高併發 高可用
高併發 提高系統併發能力的方法主要有兩種 前者垂直擴充套件可以通過提公升單機硬體效能,或者提公升單機架構效能,來提高併發性,但單機效能總是有極限的,網際網路分布式架構設計高併發終極解決方案還是後者 水平擴充套件。網際網路分層架構中,各層次水平擴充套件的實踐又有所不同 1 反向 層可以通過 dns輪詢...
高併發下搶購
了解高併發以及怎麼處理後,測試一下專案中下單的 邏輯很簡單,goods表中stock設定為unsigned。剛開始你可能會覺得這樣會出現超單的情況,但是測試後,沒有出現超單的情況。看似沒有問題,但是看過日誌發現問題還挺多的。這之前請看下這篇文章裡面有處理高併發下單的情況。goods id num g...
高併發與高可用
事發事中 事後高併發 增加處理人手 事前 副本 隔離 配額 提前預案 探知 事發 監控 報警 事中 降級 回滾 應急預案,fail 系列 事後 覆盤 思考 技改 fail 系列 當出現下游呼叫失敗時,我們一般有幾種處理方式 failretry,即失敗重試,需要配合退避時間,否則馬上重試不一定會有效果...