千萬級DAU系統該如何設計

danny_2018發表於2022-03-02

前段時間西安一碼通的故障引起了業界廣泛的討論,究其根本原因還是系統未充分考慮到擴充套件性,在面臨超過日常訪問數倍甚至十倍以上的突發流量時某個環節達到了瓶頸點,並且系統不能做到自動擴縮容,最終導致了故障。

而之前各個網站頻繁崩潰登上微博熱搜,也是在應對突發流量方面做的不是很好,一方面是因為系統的冗餘度評估不足,流量超出了系統的最大承載能力;另一方面是因為系統不能做到自動擴縮容,在流量超過系統最大承載時需要人工介入,響應速度和故障恢復速度都遠遠比不上自動擴縮容。

1

通用百萬級 DAU 使用者系統架構設計

在闡述千萬級 DAU 系統的架構設計之前,我們首先來看一個通用的百萬級 DAU 網際網路應用架構的設計。如下圖所示,一次使用者訪問請求通常要經過以下幾層:

1.1

DNS

DNS 最主要的作用是根據使用者的 IP 地址,決定把請求解析到哪個地域的 IDC,一般大型網際網路公司往往不止一個 IDC,為了訪問速度考慮,北方使用者多訪問聯通機房,南方使用者多訪問電信機房。正常情況下每個使用者請求的 DNS 解析是固定的,並且在客戶端留有快取,如果以前訪問聯通機房就會一直訪問聯通機房,以前訪問電信機房也會一直訪問電信機房。

1.2

四層負載均衡

流量經過 DNS 解析後第一個要訪問的就是四層負載均衡了。四層負載均衡主要起到流量轉發作用,比如根據請求的域名決定流量轉發到後端哪個七層閘道器叢集。四層負載均衡裝置有軟負載也有硬負載,最典型的軟負載是 LVS,單臺承載能力通常是十萬級 QPS 以上。而硬負載如 F5,單臺承載能力達到百萬級 QPS,不過成本也較高,單臺機器成本幾十萬以上,所以一般網際網路公司四層負載均衡裝置主要採用軟負載 LVS。

1.3

七層負載均衡

七層負載均衡一般又叫做閘道器,一般網際網路公司透過 Nginx 搭建自己的閘道器叢集,當流量經過四層負載均衡轉發後,就到了具體某個七層閘道器叢集了。為什麼有了四層負載均衡後還要有七層負載均衡呢?主要有以下兩方面的考慮:

應用層的轉發

對於大型網際網路公司應用來說,通常業務包括幾十個甚至上百個域名,不僅要針對域名來做四層流量的負載均衡,還要針對統一域名下不同的介面來做七層流量的負載均衡,比如上下行介面的拆分,核心和非核心介面的拆分等。

整合鑑權、日誌、監控等通用功能

除此之外,一些通常的介面功能需求,如介面呼叫鑑權、日誌統計、耗時監控等等,適合放在閘道器層統一進行處理,而不需要每個介面都實現這些功能。

1.4

服務端

流量經過閘道器轉發後,就可以訪問某臺具體 IP 的伺服器了,實際的應用程式就部署在伺服器上。服務端的程式部署一般有兩種架構:

單體應用

單體應用就是所有的業務的程式碼開發、合併、打包、部署都整合在一起,通常適合於比較簡單的業務或者團隊規模比較小的團隊。

微服務拆分

當應用的介面上百個或者是團隊規模超過十人時,程式碼開發、合併、打包、部署在一起就會引起開發效率的降低,這個時候就適合進行微服務拆分了,把相同領域的介面拆分到一個應用,獨立進行程式碼開發、合併、打包和部署,更加靈活。

1.5

快取

業務流量到達服務端後,服務端通常需要請求資料庫,再組裝處理後返回。一般情況下資料庫的延遲在十毫秒以上,為了提高訪問速度,可以把經常訪問的資料放到快取中,當前用的最多的如 memcached、redis 等,單機的承載能力都是十萬級別,並且延遲只有 1-2 毫秒。

1.6

資料庫

一般情況下使用者請求的資料大部分都被快取住,但快取的命中率不可能達到 100%,穿透過來的請求還是要訪問資料庫。為了高可用資料庫層面一般要做到以下幾個層面:

主從分離

一般網際網路應用來說,都是讀多寫少,為此可以將讀寫分離,寫請求訪問主庫,讀請求訪問從庫,根據讀請求的量來決定從庫的數量。

分庫分表

一般單臺伺服器的磁碟容量通常在 T 級別,而大型網際網路應用的資料總量一般在百 T 甚至千 T 級別,顯然單機無法承載,因此要對資料庫進行分庫。另一方面單表查詢的效能會隨著容量增加而逐漸衰減,一般情況下單表容量要控制在千萬行級別,因此也需要對資料庫進行分表。分庫分表一般有兩個維度,一個是時間維度,不同時間的資料儲存在不同的表上,這樣單張表的容量就有限了;一個是訪問維度,比如以使用者 ID 為維度,按照使用者 ID 進行 hash,把不同使用者 ID 的訪問分散到不同的資料庫埠上。

基本按照以上架構支撐百萬級 DAU 的使用者訪問通常是沒問題的,但對於千萬級甚至億級以上 DAU 的系統來說, 只有在各層都支援自動擴縮容並配合快速降級等手段,才能在面對突發峰值流量時不至於崩潰。筆者結合過去十年在一線網際網路公司的實際經歷,總結了千萬級 DAU 以上系統架構需要做出的改進。

2

混合雲架構

當使用者的請求經過 DNS 解析後,就決定了要訪問哪個機房。首先要求機房出口總頻寬要足夠大,這是使用者流量的入口,如果頻寬打滿使用者請求就失敗了。一般情況下,機房出口頻寬是固定的,不能實時擴容,所以要預留足夠的冗餘。但實際情況下,各公司機房出口頻寬不可能無限擴容。為此可以利用公有云來解決機房出口頻寬有限的問題,可以將業務部署在公有云機房,日常情況下流量主要走私有機房,當流量上漲超出私有機房出口頻寬的承載值時,可以把一部分流量切換到公有云上,這就要求系統能支援混合雲架構。

混合雲架構要求業務不僅要能部署在私有云機房,還要能部署在公有云。首先要求私有云和公有云機房之間的網路互通,對於千萬級 DAU 以上的系統來說,通常需要專線才能保證頻寬和穩定性需求。其次要考慮哪些層部署在公有云上,一個可以參考的架構如下圖所示。

以上混合雲架構要求業務在私有云和公有云上都能夠部署服務,這對業務來說是一個比較大的挑戰,需要有相應的混合雲平臺支撐,不僅要向業務遮蔽公有云和私有云的資源差異,還要能支援業務同時部署在公有云和私有云上。一個比較好的解決方案是企業在現有的運維基礎設施上整合開源算力引擎 BridgX(),它支援從不同的公有云上獲取資源,並管理私有云和公有云的機器,透過 Kubernetes 切割並以固定 IP 形式輸出等功能,只需要很小的開發成本即可支援混合雲部署。

3

全鏈路彈性擴容

當使用者流量訪問超過現有機房的承載能力時,可以把一部分流量切換到公有云上,這時候就要求公有云上部署的四七層、服務端、快取和資料庫都要能支撐流量。

3.1

四七層

雲上四層單個 SLB 能承載的併發連線數可達百萬級,因此在四層預留多幾臺 SLB 即可支撐幾百萬連,因為 SLB 是按照流量收費的, 日常沒有流量成本也很低。而七層可以根據流量來實時彈性擴容,以 Nginx 為例,單臺 Nginx 的承載能力通常在十萬級,可以根據實際的 QPS 來決定需要 Nginx 的數量,彈性擴容後實時掛載到 SLB 上。

3.2

服務端

通常服務端是無狀態的,可以根據流量實時彈性來應對。但這一層的彈性擴容不能簡單的根據 QPS 來判定,還需要考慮耗時、慢速比等因素。一個通用的解決方案是根據介面的耗時分佈對 QSP 加權,擬合服務端實際的壓力值,再透過壓測獲取服務端最大承載能力,那麼最大承載能力除以實際壓力值就是服務端的實時冗餘度,最後劃定最高冗餘度和最低冗餘度兩條線,即可自動擴縮容。目前有一個比較好的開源解決方案 CudgX(https://github.com/galaxy-future/cudgx),它可以透過各類服務的多維度、大規模的日誌資料採集以及機器學習訓練分析,對服務進行數字化、指標化度量,從而使業務能夠做更加精準的服務自動擴縮容 (https://github.com/galaxy-future/cudgx),它可以透過各類服務的多維度、大規模的日誌資料採集以及機器學習訓練分析,對服務進行數字化、指標化度量,從而使業務能夠做更加精準的服務自動擴縮容)。

3.3

快取和資料庫

為了應對千萬級 DAU 以上的系統訪問,快取也要支援擴容。但由於快取載入熱資料需要時間,往往以天為單位,如果是業務流量上漲比較快,這時候靠彈性擴容往往難以應對,最好預留足夠的冗餘度。與快取擴容類似,資料庫的彈性擴容也需要較長時間,因為涉及到資料同步,以 MySQL 的擴容為例,若一個埠的資料量在 T 級別的話,資料同步往往在小時級以上。如果是流量上漲比較快的業務,則資料庫層面也要保持充足的冗餘度。

4

三級降級機制

為了保障千萬 DAU 級的業務,業務除了要支援全鏈路彈性擴容以外,還要能夠支援降級。降級一般是主動犧牲某些系統功能和使用者體驗,為了能夠快速釋放系統冗餘度的自保措施。為了最大限度的降低降級帶來的影響,通常降級要分為三級:

一級降級是使用者感知不到的降級,降級能釋放的冗餘度往往有限,通常在 30%以下;

二級降級是使用者可以感知到的降級,降級也能釋放一定的冗餘度,通常在 50%以下;

三級降級是比較嚴重的降級,對使用者體驗的影響比較嚴重,釋放的冗餘度可達到 50%-100%,不到最後時刻一般不會採用。

實際在保障千萬級 DAU 的系統時,除了要做到混合雲架構、全鏈路彈性擴容、三級降級機制以外,還需要有各種各樣的配套機制,比如決策支援系統、值班報警機制等。

來自 “ 科技新聞賈知道 ”, 原文作者:科技新聞賈知道;原文連結:https://new.qq.com/omn/20220228/20220228A08URP00.html,如有侵權,請聯絡管理員刪除。

相關文章