我相信每一位開發(fā)同學多多少少都想?yún)⑴c或負責一個高用戶、高訪問、高并發(fā)的系統(tǒng)吧。一來可以增加自己實際的項目經(jīng)驗,有應對高并發(fā)場景的解決方案,二來是有個高并發(fā)的項目經(jīng)驗無疑是自己簡歷的一個大大的加分項。
但是奈何很多人都沒有機會可以參與這樣的項目,本文從以下幾點介紹一下設計一個高流量高并發(fā)的系統(tǒng)需要經(jīng)歷哪些步驟以及考慮哪些因素(文章中的不足之處還請大佬們多多指點)。
1、設計原則
1.1、系統(tǒng)設計原則
在設計一個系統(tǒng)之前,我們先要有一個統(tǒng)一且清晰的認知:不要想著一下就能設計出完美的系統(tǒng),好的系統(tǒng)是迭代出來的。不要復雜化,要先解決核心問題。但是要有先行的規(guī)劃,對現(xiàn)有的問題有方案,對未來系統(tǒng)有預案。
在設計高并發(fā)的系統(tǒng)時要遵循以下幾個原則:
無狀態(tài)原則
什么是無狀態(tài)?服務器不保存狀態(tài),對單次請求的處理不依賴別的請求就是無狀態(tài),主要是為了在應對高并發(fā)時方便水平擴展。
拆分原則
在我們的系統(tǒng)體積過于龐大或者承載不了大量的請求時,就要考慮拆分系統(tǒng),將復雜問題簡單化或?qū)⒘髁糠稚⒉煌酉到y(tǒng)分擔壓力??梢园凑找韵聨讉€維度進行拆分:
- 系統(tǒng)維度: 比如電商系統(tǒng),我們可以拆分成商品、支付、優(yōu)惠券多個子系統(tǒng)。
- 功能維度: 將系統(tǒng)按功能再次拆分。
- 讀寫維度: 按照讀寫比例將服務拆分成讀服務和寫服務。
- 模塊維度: 將系統(tǒng)按照基礎架構、消息隊列、分庫分表 、組件等模塊進行拆分維護。
服務化原則
當我們的系統(tǒng)被拆分的足夠大時,一旦發(fā)生故障靠人工來處理是非常耗時耗力。這個時候就可以通過注冊發(fā)現(xiàn)、限流、熔斷、降級等方案讓每個服務可以自己處理問題來幫助我們減少排障成本。
1.2、業(yè)務設計原則
在進行業(yè)務設計時要遵循一些最基本的原則比如:
- 防重原則
在某些場景下要防止用戶重復操作,例如:用戶注冊、用戶下單、用戶支付等。我們需要在客戶端和服務端有一些方案避免這種問題。
- 模塊復用原則
在業(yè)務中每個功能多多少少是有聯(lián)系的,在設計的時候模塊盡量要獨立,其他模塊直接調(diào)用即可,調(diào)用減少代碼的冗余。
- 可追溯原則
在程序的運行中避免不了業(yè)務問題以及故障的發(fā)生,但是我們可以通過日志的方式快速定位問題,做到有據(jù)可查。
- 反饋原則
系統(tǒng)對用戶的響應應該是具體、詳細的,舉一個很簡單的例子,用戶登錄失敗后應該反饋給用戶的是“用戶名錯誤”或者“密碼錯誤”,而不是“登錄失敗”。
- 備份原則
做好代碼備份、數(shù)據(jù)備份以及人員備份。
基于 Spring Boot + MyBatis Plus + Vue & Element 實現(xiàn)的后臺管理系統(tǒng) + 用戶小程序,支持 RBAC 動態(tài)權限、多租戶、數(shù)據(jù)權限、工作流、三方登錄、支付、短信、商城等功能
- 項目地址:https://github.com/YunaiV/ruoyi-vue-pro
- 視頻教程:https://doc.iocoder.cn/video/
2、客戶端優(yōu)化
在高并發(fā)高流量的系統(tǒng)客戶端的優(yōu)化是必不可少的,如果沒有做好客戶端的優(yōu)化影響用戶體驗是一方面,有時候甚至是致命的。
這里分享下我之前慘痛的教訓:之前參與過一個秒殺的業(yè)務,就是因為前端的沒有做優(yōu)化,大量用戶在刷新頁面時服務器的帶寬被打爆,頁面加載不出來,影響了系統(tǒng)的發(fā)展,這是非常致命的。主要原因還是沒有經(jīng)驗,以為后端做好高并發(fā)抵抗就可以。
客戶端優(yōu)化主要集中以下幾點:
資源下載
- 減少不必要傳輸:例如減少cookie使用,因為cookie 隨著請求發(fā)送而發(fā)送從而增加數(shù)據(jù)量。
- 減少數(shù)據(jù)量輸出:例如刪除JS無效注釋,一來可以減少體積,二來可以提高代碼安全?;蛘呖梢詫⑽募嚎s后傳輸。
- 減少請求 :將資源數(shù)目多、體積小、頻繁創(chuàng)建http請求的文件合并,比如JS合并、矢量圖 SVG。
- 轉(zhuǎn)移第三方:將請求轉(zhuǎn)移至第三方,例如oss。
資源緩存
常見的資源緩存就是圖片、樣式和腳本。有些場景可以利用客戶端的緩存幫助服務端分擔壓力,比如網(wǎng)約車中的預估價格,客戶端可以緩存計算規(guī)則并緩存,減少向服務端的請求。
資源解析
我們知道頁面中資源解析的順序是從上到下,如果上面有改變下面也需要變動,所以我們要縮小回流、重繪的范圍,比如虛擬dom。除此之外我們還可以利用懶加載和預加載進行優(yōu)化:
- 懶加載: 先加載基礎的,再根據(jù)用戶的操作進行局部加載。將原來一次性要加載的拆分成多次加載,減少下載數(shù)量和耗時。比如:樹節(jié)點、折疊面板、二級菜單等。
- 預加載: 當前頁面對下個頁面的解析、拉取資源。下面代碼作為參考
"x-dns-prefetch-control"content="on">
'dns-prefetch"href="www.baidu.com">
preload"href="..js">
href="..js">
基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實現(xiàn)的后臺管理系統(tǒng) + 用戶小程序,支持 RBAC 動態(tài)權限、多租戶、數(shù)據(jù)權限、工作流、三方登錄、支付、短信、商城等功能
3、使用CDN
CDN應用在客戶端——>服務端之前,能夠?qū)崟r的根據(jù)網(wǎng)絡流量和各節(jié)點的連接、負載情況以及到用戶的距離和響應時間等綜合信息將用戶的請求導向離用戶最近的服務節(jié)點上,使用戶可以就近取得所需內(nèi)容,解決網(wǎng)絡擁擠的狀況,提高用戶訪問網(wǎng)站的響應速度和成功率。我們可以通過CDN服務商購買CDN服務,綁定我們的域名,其他的事就不用我們管了。
借用一張網(wǎng)絡上的圖片幫助理解下

4、服務的集群
通常高并發(fā)系統(tǒng)都存在集群節(jié)點,為了抵抗大量的請求,也為了系統(tǒng)的高可用。根據(jù)業(yè)務場景利用負載策略將一個請求分發(fā)到集群中的某個計算節(jié)點。通過Nginx、LVS、Keepalived等集群組件可以輕松的實現(xiàn)這一功能。
依然是借用一張網(wǎng)絡上的圖片

5、服務端緩存
緩存的介入其實就是空間換時間,常見的緩存組件redis、memcache、guava都可以起到減少響應時間的作用,在高并發(fā)的項目中經(jīng)常被使用到,適合讀多寫少、耗時長的查詢場景。但是會帶來開發(fā)人員學習、寫代碼、部署機器、維護的成本。在設計key時要有以下幾點認知:
- 盡量避免沖突碰撞。
- sha-256沖突極低。
- 查詢key的速度取決于物理位置。
否則使用緩存的收益是非常低甚至沒有必要的。
當然,緩存技術的引入也是可能會帶來一些列緩存問題,比如緩存擊穿、緩存穿透、緩存雪崩等,依然需要代碼層面去解決,在使用時需要注意這些問題。
6、數(shù)據(jù)庫優(yōu)化
我們知道所有的業(yè)務數(shù)據(jù)最終都會落到數(shù)據(jù)庫,隨著數(shù)據(jù)量的增加會帶來響應時間的增加,以及系統(tǒng)的負載不斷上升,數(shù)據(jù)庫單點壓力會越來越大,這個時候?qū)?shù)據(jù)庫的優(yōu)化就不單僅是冗余、反范式、索引,可以根據(jù)業(yè)務場景參考以下方案:
- 表分區(qū)
在mysql中一張表的數(shù)據(jù)對應一個ibd文件,當文件過大時查找數(shù)據(jù)就會變的很慢。表分區(qū)是將一張表按照hash、list、key等規(guī)則進行分流,在物理上將這一張表ibd文件分成多個文件,但是邏輯上還是一張表。訪問量不大,但是表數(shù)據(jù)很多的表,可以采用這種方式,這樣的好處就是查詢的數(shù)據(jù)在一個分區(qū)時會很快的查到。
- 分庫分表
分庫分表是真正的把一張表分布在不同的庫或多張表,在訪問量大的時候可以把一張表分多張表并且分布在不同的庫減少單個數(shù)據(jù)庫的壓力,提高并發(fā)。或者按照業(yè)務劃分進行分庫分表達到數(shù)據(jù)隔離的作用。但是這種方式往往會帶來分布式id、事務、join查詢等一系列問題,我們只能通過代碼層面來解決,無疑增加了復雜度。
- 讀寫分離
在讀多寫少的場景下我們可以利用shardingjdbc、mycat等開源框架或組件路由到寫庫或者讀庫實現(xiàn)讀寫分離。同樣讀寫分離也存在一定的問題,比如主從復制問題、時間差問題等,可以結合業(yè)務場景規(guī)避。
7、服務治理
在高并發(fā)的項目中,往往我們的后端服務是很龐大的,因為服務拆分所引發(fā)的如:服務調(diào)用、服務雪崩、節(jié)點故障問題,以及處理高并發(fā)請求的問題。如何解決這些問題,讓服務更穩(wěn)定地運行,我們管它叫作服務治理。通常有以下幾種方案:
- 降級: 在高并發(fā)的請求下,如果服務資源不足,我們可以丟車保帥,將功能減弱保障核心業(yè)務。
- 熔斷: 通常服務間的調(diào)用可能會發(fā)生服務雪崩的情況,為了防止這種情況發(fā)生,我們?yōu)閱蝹€服務設置保險絲,當外部系統(tǒng)不能訪問后禁止調(diào)用。
- 限流: 根據(jù)資源或者服務的QPS、線程數(shù)情況限制請求量或資源量進行自我保護。
- 隔離: 隔離通常是為了達到不因某個資源異常而影響其他資源的正常使用。比如數(shù)據(jù)隔離(分庫)、機器隔離(重要的用戶單獨配置服務器)、機房隔離等。
總結
做好一個高流量高并發(fā)的系統(tǒng),不論前端還是后端,過程中每一個步驟都是至關重要的。設計一個系統(tǒng)除了滿足功能性,還要考慮兼容性、易用性、可靠性、安全性、可維護性、可移植性等軟件質(zhì)量。同時要對系統(tǒng)的吞吐量、并發(fā)數(shù)、平均響應時間等指標要完全掌握,在指標異常時可以快速做出決策避免一系列問題發(fā)生。
審核編輯 :李倩
-
模塊
+關注
關注
7文章
2787瀏覽量
50321 -
服務器
+關注
關注
13文章
9786瀏覽量
87895 -
子系統(tǒng)
+關注
關注
0文章
115瀏覽量
12829
原文標題:面試官:設計一個高流量高并發(fā)的系統(tǒng),有哪些要點?
文章出處:【微信號:芋道源碼,微信公眾號:芋道源碼】歡迎添加關注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
【明天會更好】教你避開外企面試“高級”錯誤
怎樣讀懂面試官的心
面試時,自我介紹三禁忌
7個面試禁忌回答
以下五種人面試最難成功
善用“微表情”打動面試官
千萬別這么回答面試官問題!
華為面試改革,你怎么看?
未來用機器人做面試官,可靠嗎
java軟件工程師的一次面試經(jīng)歷
高并發(fā)系統(tǒng)的藝術:如何在流量洪峰中游刃有余

程序員去面試只需一個技能征服所有面試官!

評論