[分散式]架構設計原則--高併發

加瓦一枚發表於2019-02-12

高併發設計可以從以下幾方面考慮:

  • 無狀態

  • 拆分

  • 服務化

  • 訊息佇列

  • 資料異構

  • 快取

  • 併發化

1. 無狀態

無狀態的應用容易進行水平擴充套件。

實際常用:應用無狀態,配置檔案有狀態,例如,不同的機房讀取不同的配置檔案,通過配置中心指定。

2. 拆分

拆分維度:

  • 系統維度:根據業務功能拆分,例如商品系統、購物車、結算、訂單系統。

  • 功能維度:對一個系統進行功能再拆分,比如,優惠券系統可以拆分為建立系統、領券系統、用券系統。

  • 讀寫維度:根據讀寫比例進行拆分,例如,商品系統中讀的量大於寫,可以拆分為商品寫服務、商品讀服務;寫的量大時,可以分庫分表。

  • 模組維度:按照基礎或者程式碼維護特徵進行拆分,例如基礎模組分庫分表、資料庫連線池等;程式碼結構按照三層結構劃分。

3. 服務化

服務化需要考慮自動服務註冊,和服務發現,還有服務的分組/隔離,例如,有的系統訪問量,導致把整個服務打掛,因此,需要為不同的呼叫方提供不同的服務分組,隔離訪問。

後期隨著呼叫量的增加還要考慮限流、黑白名單等。

還有一些其他的注意點,例如超時時間、重試機制、服務路由、故障補償等。

4. 訊息佇列

訊息佇列用來解耦一些不需要同步呼叫的服務,或者訂閱一些自己系統關心的變化。

訊息佇列可以實現服務解耦、非同步處理、流量銷峰等,例如,訂單產生系統、定期推送系統、訂單風控系統等等。

使用訊息佇列,需要考慮如何處理訊息傳送失敗,以及重複消費的情況。

有的訊息佇列有自動重試功能,如果重試多次還未成功,就通知傳送失敗,這時,就要做好後續的資料處理工作,例如持久化資料要同時增加日誌、報警等。

對於訊息重複消費問題,需要在業務層面進行防重處理。

應用示例:電商促銷時,流量會比平時高出幾倍甚至幾十倍,這就需要特殊的設計來保證系統平穩,一般是犧牲強一致性,保證最終一致性,如扣減庫存,直接在 redis 中扣減,記錄下日誌,通過 worker 同步到資料庫。

 

再比如訂單系統,可以這樣設計:

 

結算服務呼叫訂單接單服務,將訂單儲存到 redis 和訂單佇列中。訂單redis用於使用者檢視訂單詳情,通過佇列提升接單能力。

然後通過同步Worker把佇列中的訂單同步到資料庫。

當訂單狀態發生變化,例如使用者支付了,訂單狀態機負責驅動狀態的變更,更新資料庫和redis。

5. 資料異構

資料量大了以後,通常會分庫分表,例如訂單表,拆分時通常根據訂單ID進行劃分,但如果查詢某個使用者的訂單時,就比較麻煩了,需要聚合多個表,這種情況一般都會生成一個“使用者ID”維度的資料,供業務直接呼叫。或者有跨庫join查詢時,將需要join的多個表按照某個維度又聚合在一個庫中。這類做法就叫做“資料異構”。

 

6. 快取

(1)瀏覽器、APP客戶端快取

(2)CDN 快取

(3)應用層快取

(4)分散式快取,應用示例:

 

7. 併發化

例如一個讀服務需要如下資料:

 

如果序列,共需要60ms。

如果 C 依賴 A 和 B,D 沒有任何依賴,E 依賴 C,那麼就可以並行獲取資料:

 

併發化處理,共需要30ms,效能提升了一倍。

總結

 

內容整理自張開濤的《億級流量網站架構核心技術》,推薦詳讀。

相關文章